2012-10-15 26 views
6

Tôi đang sử dụng EF 5 mã đầu tiên và tôi có 2 đơn vị liên quan ApplicationPermission và Ứng dụng:Làm cách nào để xóa một đối tượng có thuộc tính điều hướng có mã khung thực thể 5 trước?

public class ApplicationPermission 
{ 
    public virtual Application Application { get; set; } 

    public int Id { get; set; } 
} 

public class Application 
{ 
    public string Name { get; set; } 

    public int Id { get; set; } 
} 

với các bản đồ sau đây cho ApplicationPermission:

HasKey(x => x.Id); 
HasRequired(x => x.Application).WithMany().Map(m => m.MapKey("ApplicationId")).WillCascadeOnDelete(false); 

và cho ứng dụng:

HasKey(x => x.Id); 

Tôi sử dụng mã bên dưới để xóa ApplicationPermission:

ApplicationPermission entity = new ApplicationPermission { Id = id }; 
DbContext.Set<ApplicationPermission>().Attach(entity); 
DbContext.Set<ApplicationPermission>().Remove(entity); 
DbContext.SaveChanges(); 

Nhưng tôi đã nhận ra lỗi trên phương pháp SaveChanges:

Đối tượng trong 'CodeFirstContainer.ApplicationPermissions' tham gia vào của ApplicationPermission_Application 'mối quan hệ. 0 liên quan 'ApplicationPermission_Application_Target' đã được tìm thấy. 1 'ApplicationPermission_Application_Target' được mong đợi.

Làm cách nào để xóa ApplicationPermission mà không tải ứng dụng vào dbcontext?

Trả lời

3

Tôi tin rằng không thể xóa đối tượng mà không cần đặt thuộc tính điều hướng bắt buộc khi bạn sử dụng các liên kết độc lập. Bạn phải tải Application từ cơ sở dữ liệu hay - ít nhất - biết giá trị chính nước ngoài và đính kèm một thực thể Application với giá trị đó, như vậy:

ApplicationPermission entity = new ApplicationPermission { Id = 1 }; 
entity.Application = new Application { Id = 5 }; 
DbContext.Set<ApplicationPermission>().Attach(entity); //attaches Application too 
DbContext.Set<ApplicationPermission>().Remove(entity); 
DbContext.SaveChanges(); 

Lệnh SQL được tạo ra khi bạn gọi SaveChanges là sau đó:

exec sp_executesql N'delete [dbo].[ApplicationPermissions] 
where (([Id] = @0) and ([ApplicationId] = @1))',N'@0 int,@1 int',@0=1,@1=5 

Như bạn có thể thấy các truy vấn cho delete không chỉ yêu cầu các Id của ApplicationPermission xóa mà còn (and) giá trị khóa ngoại cho ApplicationId. Để thành công, bạn phải biết và đặt giá trị FK này bằng cách đặt thực thể liên quan với cùng một khóa chính.

Vấn đề không xảy ra khi sử dụng hiệp hội khóa ngoại:

public class ApplicationPermission 
{ 
    public virtual Application Application { get; set; } 
    public int ApplicationId { get; set; } 

    public int Id { get; set; } 
} 

Mapping:

modelBuilder.Entity<ApplicationPermission>() 
    .HasRequired(x => x.Application) 
    .WithMany() 
    .HasForeignKey(x => x.ApplicationId) 
    .WillCascadeOnDelete(false); 

Sau đó bạn có thể sử dụng mã ban đầu của bạn mà không cần thiết lập thuộc tính ApplicationId FK đến một giá trị đúng (sẽ mặc định là 0 rồi) và không đặt thuộc tính điều hướng và xóa đối tượng sẽ hoạt động. Lệnh SQL không quan tâm đến FK và chỉ truy vấn cho Id của ApplicationPermission xóa:

exec sp_executesql N'delete [dbo].[ApplicationPermissions] 
where ([Id] = @0)',N'@0 int',@0=1 

Tôi không có ý tưởng tại sao các lệnh SQL khác nhau giữa hai loại của các hiệp hội.

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