[英]Entity Framework: how to delete related entity upon update or delete of 'generic' parent
我有一個Product
類,其中包含一個Picture
屬性。 其他類也可能有圖片,例如Customer
可以有Picture
。
Product.cs:
public class Product
{
public Picture Picture { get; set; }
}
Customer.cs:
public class Customer
{
public Picture Picture { get; set; }
}
Picture.cs:
public class Picture
{
public string Type { get; set; }
public byte[] Content { get; et; }
}
圖片始終是可選的 ,即產品和客戶可能有也可能沒有圖片。 但是,圖片唯一地鏈接到一個“父”實體(產品或客戶)。 沒有父母,圖片就沒有用。 請注意,從Picture到父類沒有鏈接,因為該父類可以是多種類型(產品或客戶)。
另一個要求是我想通過急切或延遲加載來完全控制是否加載圖片。 例如,當檢索產品列表時,我不希望獲取圖片,但是如果需要單個產品,則應包含圖片。
我的問題 :如何配置實體框架,以便:
我正在使用流暢的API來定義關系。 當前,沒有任何級聯刪除。
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
ToTable("PRODUCTS");
HasKey(x => x.Id);
HasOptional(x => x.Picture).WithOptionalDependent().Map(m => m.MapKey("PICTUREID"));
}
}
我嘗試使用WithRequired,但這會產生錯誤,因為從Picture
到Product/Customer
沒有鏈接或外鍵。
您可以執行以下操作:
public abstract class Picture
{
public int Id {get;set;}
public string Type { get; set; }
public byte[] Content { get; set; }
}
public class ProductImage:Picture
{
public int ProductId {get;set;}
public virtual Product Product {get;set;}
}
public class CustomerImage:Picture
{
public int CustomerId {get;set;}
public virtual Customer Customer{get;set;}
}
那么您可以像這樣配置:ex。 產品:
HasOptional(x=>x.ProductImage)
.withRequired(x=>x.Product)
.HasForeignKey(x=>x.ProductId); //cascade on delete is default true
這樣,您可以在需要時加載圖片,並且如果刪除產品項目,圖像也將被刪除。 該圖像是可選的,並且可以替換。 更新時,您必須指定新圖像或刪除舊圖像。
希望這種替代方法將幫助您選擇所需的確切對象。
我認為您可以將Picture
配置為ComplexType
,這將在父表中創建Picture
類列的屬性。
這意味着:
Picture
。 Picture
數據(更新的圖片數據或無數據)更新父對象時,父表中的相應列也會更新。 此處介紹了如何將Picture
實體配置為ComplexType
: http : ComplexType
。
至少這是您需要做的:
public class MyDbContext:DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.ComplexType<Picture>();
}
}
如果運行migration
則可能會生成類似於以下內容的遷移:
public override void Up()
{
CreateTable(
"dbo.Customers",
c => new
{
Id = c.Int(nullable: false, identity: true),
Picture_Type = c.String(),
Picture_Content = c.Binary(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Products",
c => new
{
Id = c.Int(nullable: false, identity: true),
Picture_Type = c.String(),
Picture_Content = c.Binary(),
})
.PrimaryKey(t => t.Id);
}
另外,您還可以為ComplexType
編寫流暢的配置,如下所示:
public class PictureConfig : ComplexTypeConfiguration<Picture>
{
public PictureConfig()
{
Property(t => t.Type).HasColumnName("PictureType");
Property(t => t.Content).HasColumnName("PictureContent");
}
}
並在DbContext
添加此配置:
public class MyDbContext:DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.ComplexType<Picture>();
modelBuilder.Configurations.Add(new PictureConfig());
}
}
如果現在使用add-migration
,它可能如下所示:
public override void Up()
{
CreateTable(
"dbo.Customers",
c => new
{
Id = c.Int(nullable: false, identity: true),
PictureType = c.String(),
PictureContent = c.Binary(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.Products",
c => new
{
Id = c.Int(nullable: false, identity: true),
PictureType = c.String(),
PictureContent = c.Binary(),
})
.PrimaryKey(t => t.Id);
}
希望這可以幫助。
根據評論進行更新:更新的這一部分並沒有真正提供您想要的內容,而只是提出了建議。
我認為您正在尋找的關系如下:
Product---1-----1---Picture ---1------1---Customer
|- Id |- Id |- Id
|- PictureId? |- PictureId?
也就是說,您可以在父類上保留nullable
PictureId
,並在更改圖片時更改此PictureId
。
缺點:您需要自己管理數據操作活動(CRUD)。
優點:這樣,您可以完全控制何時加載圖像,因為加載父級不會自動加載Picture
。 此外,這還使您能夠將Picture
與數據庫解耦,並使用某種形式的Blob存儲(可能在雲中)。
我也在StackOverflow上找到了這個,也許對您有幫助:
modelBuilder.Entity<Product>()
.HasKey(c => c.Id)
.HasRequired(c => c.User)
.WithRequiredDependent(c => c.UserProfile)
.WillCascadeOnDelete(true);
我認為您需要稍微更改代碼,但它應該可以工作...
原始帖子: EF代碼第一個Fluent API-級聯刪除
也許這也可以為您提供幫助: 使用Fluent API進行級聯刪除
添加呼叫以刪除要刪除產品的圖片。 如果要在許多地方執行此操作,請重新分解以封裝此操作。 我發現EF配置不透明,但是在DeleteProduct方法或DeleteCustomer方法中對delete的簡單調用很容易閱讀和理解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.