2012-03-19 42 views
5

IDbSetExtensions.AddOrUpdate có nghĩa là giúp viết mã hoạt động giống nhau cho dù cơ sở dữ liệu trống hoặc phổ biến. Nhưng liên kết các đối tượng cần mã khác nhau. Khi cơ sở dữ liệu trống, các đối tượng không có ID và bạn liên kết chúng bằng cách gán thuộc tính điều hướng. Tuy nhiên, khi các đối tượng đã tồn tại, các thuộc tính điều hướng không hoạt động và bạn cần phải đặt các khóa ngoại trực tiếp. Các thuộc tính điều hướng làm việc cho proxy trong cả hai trường hợp, với chi phí từ bỏ các POCO. Chỉnh sửa: Trên thực tế, proxy không hoạt động khi cả hai thực thể đều cũ.IDbSetExtensions.AddOrUpdate và các mối quan hệ

treo mẫu này trong SaveChanges thứ hai gọi, khi EF cố gắng thiết lập CountryID 0:

public class Country 
{ 
    public virtual int ID { get; set; } 
    public virtual string Name { get; set; } 
} 

public class Person 
{ 
    public virtual int ID { get; set; } 
    public virtual string Name { get; set; } 

    public virtual int CountryID { get; set; } 
    public virtual Country Country { get; set; } 
} 

public class Context : DbContext 
{ 
    public DbSet<Person> Person { get; set; } 
    public DbSet<Country> Country { get; set; } 
} 

class Program 
{ 
    static void Foo() 
    { 
     using (var db = new Context()) 
     { 
      //var c = new Country(); 
      var c = db.Country.Create(); 
      c.Name = "usa"; 
      db.Country.AddOrUpdate(x => x.Name, c); 

      //var p = new Person(); 
      var p = db.Person.Create(); 
      p.Name = "billg"; 
      p.Country = c; 
      db.Person.AddOrUpdate(x => x.Name, p); 

      db.SaveChanges(); 
     } 
    } 
    static void Main() 
    { 
     Database.SetInitializer<Context>(new DropCreateDatabaseAlways<Context>()); 
     Foo(); 
     Foo(); 
    } 
} 

như thế nào AddOrUpdate sử dụng?

+1

tôi khuyên bạn nên đọc nó http://thedatafarm.com/blog/data-access/take-care-with-ef-4- 3-addorupdate-method/ –

Trả lời

9

IDbSetExtensions.AddOrUpdate có nghĩa là giúp viết mã hoạt động tương tự cho dù cơ sở dữ liệu trống hoặc phổ biến.

AddOrUpdate chỉ được sử dụng trong phương pháp di chuyển đầu tiên mã Seed. Nó không phải là nghĩa vụ phải được sử dụng trong mã bình thường bởi vì nó có chi phí lớn và một số hạn chế. Overhead là truy vấn bổ sung cho cơ sở dữ liệu và sự phản chiếu. Giới hạn là nó chỉ kiểm tra thực thể chính mà bạn đang truyền chứ không chỉ quan hệ của nó. Mỗi mối quan hệ được cho là bị xử lý bằng cách gọi riêng biệt để AddOrUpdate:

static void Foo() 
{ 
    using (var db = new Context()) 
    { 
     var c = new Country() {Name = "abc"}; 
     db.Country.AddOrUpdate(x => x.Name, c); 

     var p = new Person() 
     { 
      Name = "me", 
      CountryID = c.ID, 
      Country = c 
     }; 

     db.Person.AddOrUpdate(x => x.Name, p); 
     db.SaveChanges(); 
    } 
} 
+1

Tôi rút ngắn mã của tôi để dán nó ở đây. Ứng dụng của tôi chỉ sử dụng AddOrUpdate trong ghi đè DbMigrationsConfiguration.Seed. Mẫu của bạn hoạt động, nhưng tôi cảm thấy không thoải mái khi chỉ định cả Quốc gia và CountryID. Bạn có đề nghị luôn gán cả hai? Ứng dụng của tôi sử dụng các phím tổng hợp và dễ dàng hơn, rõ ràng hơn và ít bị lỗi hơn khi chỉ định thuộc tính điều hướng. –

+0

@BrunoMartinez AddOrUpdate *** sẽ không *** đặt giá trị khóa ngoài mà Thuộc tính Điều hướng (và cơ sở dữ liệu) dựa vào - ngay cả khi thực thể đó đã được 'thêm hoặc cập nhật' hoặc truy vấn trực tiếp (và EF phải là có thể sửa chữa mối quan hệ). Thực tế, bạn chỉ cần đặt FK ***, trừ khi bạn cần điều hướng các mối quan hệ sau này trong hạt giống. Hơn nữa, nếu bạn muốn sử dụng mối quan hệ như một phần của 'identifierExpression', bạn phải sử dụng Id FK vì nó phải là giá trị nguyên thủy hoặc enum và thuộc tính được ánh xạ tới một cột - các thực thể khác không thể được sử dụng. – JoeBrockhaus

+0

RE: * "dễ dàng hơn, rõ ràng hơn và ít lỗi hơn để chỉ định thuộc tính điều hướng." * Tôi khuyên bạn nên thêm một số phương thức mở rộng cho các thực thể của bạn vào 'AddRelatedEntity (RelatedEntity entity) {..}' hoặc chỉ sử dụng native Các phương thức DbSet' về cơ bản sẽ viết 'AddOrUpdate()' của riêng bạn. Nó * là * bực bội rằng bề mặt API này không tuân theo các quy ước tương tự như phần còn lại của các hoạt động DbContext/DbSet. ¯ \\ _ (ツ) _/¯ – JoeBrockhaus

Các vấn đề liên quan