[英]Entity Framework Core : get data from related tables with include
[英]Entity Framework Related Tables Get and Save Data
我一直在NET和SO中尋找一些答案-我對Entity Framework幾乎是個菜鳥..所以我對相關實體確實有些困惑..我正在使用C#,Winforms,Linq,EF6 ^(生成的反向DB類在DAL項目中)
我無法解決這個問題。 我有3個與第4個表相關的表-第4個表使用其他3個表中的PK_ID列-配置為外鍵,它們還構成了復合鍵(主鍵)。
我的原始ER圖來自油漆。
我在EF查詢中需要做的是獲取多個數據綁定列綁定到列表視圖。
我想要的列是EnumerationCode,Part.Number,Part.Description。
我將使用ProdID(我將Products綁定到DropDown)作為這些附加值的獲取器。
因此,基本上,我要牢記這一點:從TernaryTable中選擇T在ENumTable.EnumID上加入EnumID,其中T.ProdID = myProdID,按EnumCode順序[從中選擇Part.Number,Part.Description從PartID = TernaryTable.PartID的部件中選擇)
我認為對於如何獲取此數據然后如何保存對數據的任何更改,可能有一個簡單的解決方案-但正如我所說的,我很迷惑。
我需要兩種方法,一種用於獲取數據,另一種用於保存對數據進行的任何更改。
我讀過了
但似乎我仍然對多重關系迷失了。
編輯
我認為在Haralds出色的答復之后,我需要並且可以發布更好的聲明以及真實的圖表!
現在獲取表信息:
我想要MprnEnum.RefName,Part.PartNumber,Part.Name,Part.Description,其中ProductID = [Product.ID-我將提供的此ID]由MPRNENUM.RefName排序。 我希望能夠使用VS EF從數據庫生成的實體類對ProdPartEnum執行CRUD。
有20個RefName,每個產品都有許多EnumID,並且EnumID可以屬於許多產品,每個ProdEnum具有一個關聯的部分。 許多零件可以屬於許多ProdEnums
一個典型的表條目可能如下所示:ProdID = 1,EnumID = [1-20],PartID [1-1000]其中產品ID = 1,我們有20行EnumID,每行將有一個PartNumber。
如果需要,我可以發布更多詳細信息。
我的,這是一個奇怪的多對多對多!
通常情況下,設計如下:
Product
具有零個或多個Parts
,每個Part
用於零個或多個Products
(多對多ProductPart
) Product
都有零個或多個Enumerations
,每個Enumeration
由零個或多個Products
(多對多ProductEnumeration
) Part
都有零個或多個Enumerations
,每個Enumeration
用於零個或多個Parts
(多對多EnumerationPart
) 這將導致三個聯結表ProductPart
, ProductEnumeration
和EnumerationPart
您選擇的設計只有一個連接表。
您確實意識到,在您的設計中,只要一個Product
具有Part
, Product
和Part
都具有相同的Enumeration
,不是嗎? product
Enumerations
數或其他Enumerations
不能超過product
的Parts
數。 你不能有一個Product
具有Part
但不Enumerations
。
如果您真的想將數據庫限制在此范圍內,則可以使用以下類:
class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Junction> Junctions { get; set; }
}
class Part
{
public int Id { get; set; }
public int Number { get; set; }
public string Description { get; set; }
public virtual ICollection<Junction> Junctions { get; set; }
}
class Enumeration
{
public int Id { get; set; }
public int Code { get; set; }
public virtual ICollection<Junction> Junctions { get; set; }
}
您的聯結表將如下所示:
public class Junction
{
// foreign keys; composite primary key
public int ProductId { get; set; }
public int EnumId { get; set; }
public int PartId { get; set; }
public virtual Product Product { get; set; }
public virtual Enumeration Enumeration { get; set; }
public virtual Part Part { get; set; }
}
請注意:在實體框架中,非虛擬屬性表示表中的實際列。 虛擬屬性表示表之間的關系
您的DbContext將具有四個表:
class ManyDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Enumeration> Enumerations { get; set; }
public DbSet<Part> Parts { get; set; }
public DbSet<Junction> Junctions {get; set;}
}
最后,在OnModelCreating中,您必須指定設計:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var junctionConfig = modelBuilder.Entity<Junction>();
// composite primary key:
junctionConfig.HasKey(junc => new { junc.ProductId, junc.PartId, junc.EnumId);
// every junctionconfig has a mandatory foreign key to Product in ProductId
// which represent a one-to-many (one Product has many Junctions)
junctionConfig.HasRequired<Product>(junc => junc.Product)
.WithMany(product => product.Junctions)
.HasForeignKey<int>(junc => junc.ProductId);
// every junctionconfig has a mandatory foreign key to Enumerations in EnumerationId
// which represent a one-to-many (one Enumeration has many Junctions)
junctionConfig.HasRequired<Enumeration>(junc => junc.Enumeration)
.WithMany(enumeration => enumeration.Junctions)
.HasForeignKey<int>(junc => junc.EnumId);
// every junctionconfig has a mandatory foreign key to Pars in PartId
// which represent a one-to-many (one Part has many Junctions)
junctionConfig.HasRequired<Part>(junc => junc.Part)
.WithMany(part => part.Junctions)
.HasForeignKey<int>(junc => junc.PartId);
base.OnModelCreating(modelBuilder);
}
給定一個
productId
,請給我具有該ProductId
的Product
所有EnumerationCodes
,Part.Number
,Part.Description
記錄
當使用實體框架時,人們傾向於對外鍵執行聯接,而不是在表中使用虛擬屬性,這會使事情變得更加復雜。
如果您使用虛擬屬性,則查詢將非常簡單且直觀:
var result = dbContext.Junctions
.Where(junction => junction.ProductId == productId)
.Select(junction => new
{
EnumerationCode = junction.Enumeration.EnumerationCode,
PartNumber = junction.Part.Number,
PartDescription = junction.Part.Description,
});
實體框架足夠智能,可以檢測到需要哪些聯接。
如果您確實想進行聯接,則必須對三個表進行聯接。 這樣的連接看起來很可怕:
var x = dbContext.Junctions // from all junctions
.Where(junction => junction.ProductId == productId) // take only the ones with productId
// The first join:
.Join(dbContext.Parts, // Join with Parts
junction => junction.PartId, // from the Junction take the PartId,
part => part.Id, // from the Parts take the Id
(junction, part) => new // when they match make one new object
{ // containing some properties
EnumerationId = junction.EnumId,
PartNumber = part.Number,
PartDescription = part.Description,
})
// Second Join
.Join(dbContext.Enumerations, // Join with enumerations
junction => junction.EnumerationId, // from the 1st join result take EnumerationId
enumeration => enumeration.Id, // from enumerations take Id
(junction, enumeration) => new // when they match make one new object
{ // containing your desired properties
EnumerationCode = enumeration.Code,
PartNumber = junction.PartNumber,
PartDescription = junction.PartDescription,
});
您很幸運,不需要產品的說明。 如果要使用虛擬屬性,這將很容易:
var result = dbContext.Junctions
.Where(junction => junction.ProductId == productId)
.Select(junction => new
{
Description = junction.Product.Description,
EnumerationCode = junction.Enumeration.EnumerationCode,
PartNumber = junction.Part.Number,
PartDescription = junction.Part.Description,
});
由您來編寫一個包含四個表的聯接。 查看區別並確定從現在開始要使用哪種方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.