2011-08-18 6 views
6

Tôi đang giải quyết vấn đề với việc cập nhật pháp nhân trước khi lưu vào cơ sở dữ liệu và có hành vi lạ.Thực thể lạ cập nhật trong Khuôn khổ thực thể Mã-Đầu tiên

Tôi đang sử dụng Khuôn khổ thực thể 4.1 Mã-đầu tiên trong ứng dụng web ASP.NET MVC 3. Đây là mô hình:

public class Order 
{ 
    public int OrderId { get; set; } 
    public int CarId { get; set; } 
    public DateTime BeginRentDate { get; set; } 
    public DateTime EndRentDate { get; set; } 
    public decimal RentPrice { get; set; } 
    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    public int CarId { get; set; } 
    public string Brand { get; set; } 
    public string Model { get; set; } 
    public string NumberPlate { get; set; } 
    public decimal RentPrice { get; set; } 
} 

Mỗi xe có giá thuê. Giá này phải được sao chép vào RentPrice của Lệnh khi tạo. Chiếc xe được lựa chọn bởi người dùng để ban đầu Order.RentPrice là 0.

Ở đây tôi muốn sao chép giá trị giá:

[HttpPost] 
public ActionResult Create(Order order) 
{ 
    order.RentPrice = _context.Cars.Find(order.CarId).RentPrice; 

    if (ModelState.IsValid) 
    { 
     _context.Orders.Add(order); 
     _context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(order); 
} 

Nó không làm việc vì một lỗi trên SaveChanges rằng thực thể có lỗi xác nhận. ĐƯỢC. Tôi thấy rằng trước tiên cần phải gọi UpdateModel(order); và sau đó thay đổi giá trị.

Vì vậy, những gì tôi có. đang làm việc:

_context.Orders.Add(order); 
UpdateModel(order); 
order.RentPrice = 777; 
_context.SaveChanges(); 

Không đang làm việc:

_context.Orders.Add(order); 
UpdateModel(order); 
order.RentPrice = _context.Cars.Find(order.CarId).RentPrice; 
_context.SaveChanges(); 

đang làm việc (!):

_context.Orders.Add(order); 
UpdateModel(order); 
var t = (double)_context.Cars.Find(order.CarId).RentPrice; 
order.RentPrice = (decimal)t; 
_context.SaveChanges(); 

Ai đó có thể giải thích, xin vui lòng, những gì đang xảy ra ở đây? Đặc biệt là ma thuật trên dòng 3 và 4 trong khối mã cuối cùng.

Cập nhật

Tôi nhận được DbEntityValidationException: "Validation thất bại cho một hoặc nhiều tổ chức Xem tài sản 'EntityValidationErrors' để biết thêm chi tiết.." Từ ngoại lệ bên trong: "Không thể sử dụng OriginalValues ​​cho các thực thể trong trạng thái Đã thêm."

+1

Bạn có nhận thấy bạn có hai dấu chấm phẩy ở cuối đơn đặt hàng.RentPrice = _context.Cars.Find (order.CarId) .RentPrice ;; -> ở bên cạnh khối mã cuối cùng? – Jack

+1

lỗi xác thực trên phương thức SaveChanges là gì? Mã trong phương thức Create ban đầu của bạn hoạt động tốt cho tôi. – agradl

+0

@Jack, chỉ là lỗi chính tả khi viết bài. Đã sửa. –

Trả lời

0

Bạn đã khai báo khóa chính ở bất kỳ đâu? Bạn nên làm điều đó, hoặc sử dụng FluentAPI hoặc thuộc tính như thế này:

public class Order 
{ 
    [Key] 
    public int OrderId { get; set; } 
    public int CarId { get; set; } 
    public DateTime BeginRentDate { get; set; } 
    public DateTime EndRentDate { get; set; } 
    public decimal RentPrice { get; set; } 
    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    [Key] 
    public int CarId { get; set; } 
    public string Brand { get; set; } 
    public string Model { get; set; } 
    public string NumberPlate { get; set; } 
    public decimal RentPrice { get; set; } 
} 

Hoặc trong bối cảnh của bạn, bạn có thể sử dụng API thạo tuyên bố quan trọng, như thế này

builder.Entity<Car>().HasKey(x=>x.CarId); 
builder.Entity<Order>().HasKey(x=>x.OrderId); 
+0

EF sử dụng quy ước về cấu hình (phải mất Thuộc tính Id cho việc này). Vì vậy, vâng, cơ sở dữ liệu của tôi có các khóa chính. Tôi đã kiểm tra. Và làm thế nào nó giải thích khối cuối cùng của mã? .. –

0

Tôi có một ý tưởng, nhưng nó nhiều đoán hơn ... Có lẽ vào thời điểm bạn nhận được hàm Create đó, bối cảnh đã biết về Lệnh đó? Nếu có, cố gắng thêm lại nó có thể có thể cho bạn lỗi đó.

Trong đoạn mã cuối cùng của bạn (mã hoạt động đáng ngạc nhiên), bạn đã thử sử dụng một biến trung gian mà không cần đúc để tăng gấp đôi?

Tôi cũng thích thú với UpdateModel ... Tôi sử dụng EF nhưng không phải MVC vì vậy có lẽ nó không liên quan gì đến nó, nhưng nếu đó là chức năng tùy chỉnh, nó sẽ làm gì?

18

Khi bạn nhận được

"Validation thất bại cho một hoặc nhiều thực thể. Xem tài sản 'EntityValidationErrors' để biết thêm chi tiết."Từ bên trong ngoại lệ: 'OriginalValues ​​có thể không được sử dụng cho các tổ chức trong tình trạng gia tăng '

Điều đó có nghĩa là có lỗi như collumns NOT NULL mà là trống hoặc các ràng buộc khác, kiểm tra các lỗi xác nhận thực thể bằng cách. gỡ lỗi hoặc như

try{ 
... 
catch (DbEntityValidationException ex) 
    { 
foreach (var validationErrors in ex.EntityValidationErrors) 
    { 
    foreach (var validationError in validationErrors.ValidationErrors) 
    { 
     System.Diagnostics.Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); 
    } 
    } 
} 
+0

Bạn đã đọc các ví dụ mã của tôi trong câu hỏi? –

+0

Xin lỗi tôi không có lời giải thích cho câu hỏi ban đầu của bạn chỉ là mẹo làm thế nào để có được lỗi thực sự là từ DbEntityValidationException – John

+0

Trong trường hợp của tôi tìm thấy chú thích dữ liệu không khớp giữa mô hình xem đăng ký và mô hình nhận dạng của tôi. – Dreamcasting

0

tôi chắc chắn vấn đề sẽ được sửa chữa từ lâu, chỉ muốn đóng góp 2 cent của tôi.

tôi cũng chạy vào một vấn đề với các thông báo lỗi tương tự, tôi đã sử dụng Oracle và EF 5.0. đồng minh tôi có một giải pháp sau khi lãng phí hơn 12 giờ.

Đối với tôi, nó thiếu quyền đối với người dùng trên bảng nơi tôi đang cố gắng chèn các giá trị và thông báo lỗi hoàn toàn không có gợi ý về vấn đề quyền thực sự, điều này thực sự kỳ lạ.

Hy vọng ai đó thấy điều này hữu ích và không phí phạm giờ như tôi khi khắc phục sự cố.

Chúc mừng,

Avi

1

OriginalValues ​​không thể được sử dụng cho các tổ chức trong tình trạng gia tăng.

có thể được sửa chữa bằng cách đảm bảo rằng phi sắc lĩnh vực khóa chính được quy định như không tạo trong mô hình.

modelBuilder 
    .Entity<T>() 
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
    // this can also be achieved using attributes on the entity. 

Lỗi này thực sự tự giải thích khi bạn có ngữ cảnh, nhưng có sự cố khác. Cơ sở dữ liệu tạo ra hai báo cáo cho chèn, thứ hai trong số đó là:

SELECT [PrimaryKeyId] 
FROM [dbo].[Entity] 
WHERE @@ROWCOUNT > 0 AND [PrimaryKeyId] = scope_identity() 
/* SP:StmtCompleted... */ 

Tuyên bố này sẽ không trả lại bất kỳ hàng cho phi sắc cột. Do đó, OriginalValues sẽ vẫn không bị thay đổi trong trạng thái được thêm. Điều này cũng giải thích tại sao ngoại lệ này được bao bọc trong một số OptimisticConcurrencyException vì số hàng bị ảnh hưởng được sử dụng để phát hiện dữ liệu đã thay đổi hiện có.