[英]Entity Framework Core code-first foreign key with optional linked entity
我有一個文件表,我想在其他 2 個表中引用它。 每個文件都是其中一個表獨有的,這意味着我的外鍵在至少一個鏈接表中沒有實體,某些文件可能有一個填充鍵,它根本沒有鏈接到任何實體(因為它將是稍后裝箱)。
關系:(1 -> n)
Item <- File -> Image
這會導致 insert/ SaveChanges
上的外鍵異常,因為數據庫無法找到鏈接的實體。
我搜索了一個解決方案,但找不到任何解決此問題的文章,而且我提出的解決方案至少有一個代碼異味。
問題:如何鏈接這 3 個表而不會出現數據庫異常並產生代碼/數據庫氣味?
還是整個數據架構有問題,我應該嘗試一些不同的東西(如果有的話)?
我想出但不想使用的解決方案:
Files
表拆分為ItemFiles
和ImageFiles
(我聽說這是 DB 的味道)其他信息:
縮短型號:
public class FileData
{
public Item Item { get; set; }
public ImageData Image { get; set; }
public Guid Id { get; set; }
public string HashKey { get; set; }
// ...
}
public class Item
{
public FileData[] Files { get; set; }
public Guid Id { get; set; }
public string HashKey { get; set; }
// ...
}
public class ImageData
{
public FileData[] Files { get; set; }
public Guid Id { get; set; }
public string HashKey { get; set; }
// ...
}
數據庫配置:
public class FileDataConfiguration : IEntityTypeConfiguration<FileData>
{
public void Configure(EntityTypeBuilder<FileData> builder)
{
builder.HasKey(file => file.Id);
builder.HasIndex(file => file.HashKey);
// ...
}
}
public class ItemConfiguration : IEntityTypeConfiguration<Item>
{
public void Configure(EntityTypeBuilder<Item> builder)
{
builder.HasKey(item => item.Id);
builder.HasMany(item => item.Files)
.WithOne(file => file.Item)
.IsRequired(false)
.HasForeignKey(file => file.HashKey)
.IsRequired(false)
.HasPrincipalKey(item => item.HashKey);
builder.HasIndex(file => file.HashKey);
// ...
}
}
public class ImageDataConfiguration : IEntityTypeConfiguration<ImageData>
{
public void Configure(EntityTypeBuilder<ImageData> builder)
{
builder.HasKey(image => image.Id);
builder.HasMany(image => image.Files)
.WithOne(file => file.Image)
.IsRequired(false)
.HasForeignKey(file => file.HashKey)
.IsRequired(false)
.HasPrincipalKey(image => image.HashKey);
builder.HasIndex(image => image.HashKey);
// ...
}
}
此代碼引發異常
// both examples throw an exception, independent of each other
//example 1:
dbContext.Files.Add(
new File(){
HashKey="1"
}
);
dbContext.SaveChanges();
//example 2:
dbContext.Files.Add(
new File(){
HashKey="2"
}
);
dbContext.Items.Add(
new Item(){
HashKey="2"
}
);
dbContext.SaveChanges();
通常,您的FileData
實體應包含Item
和ImageData
實體的Guid
外鍵,而不僅僅是導航屬性,即Guid ItemId
和Guid ImageId
。 例如:
public class FileData
{
public Guid ItemId { get; set;}
public Item Item { get; set; }
public Guid ImageId {get; set; }
public ImageData Image { get; set; }
public Guid Id { get; set; }
public string HashKey { get; set; }
// ...
}
同樣在 Fluent Api 中同時配置Item
和ImageData
時,此配置應該足夠了
builder.HasMany(item => item.Files)
.WithOne(file => file.Item)
.OnDelete(DeleteBehavior.NoAction);
最后我決定放棄外鍵,因為我不需要更新其他實體並手動啟動文件查詢。 似乎不可能將文件添加為屬性,因為錯誤一直被拋出(我嘗試了這個解決方案) 。
使用的約束列表:Item.Id => Key Item.Hash => Indexed, Unique
Image.Id => 關鍵 Image.Hash => 索引,唯一
File.Id => 密鑰 File.Hash => 索引,不唯一
我決定保留 Item 和 Image 的 ID 的原因之一是其他實體主要通過 ID 引用這些,而不是 hash 和 hash 可能會更改,需要大量更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.