实体框架相关表获取和保存数据

时间:2018-08-21 02:40:08

标签: c# winforms entity-framework linq relationship

我一直在搜索 NET SO 来寻找一些答案-我几乎不愿意实体框架..所以我对相关实体有些困惑..我正在使用C#,Winforms,Linq,EF6 ^(DAL项目中的生成的反向DB类)

我很难解决这个问题。我有3个与第四个表相关的表-第四个表使用其他3个表中的PK_ID列-配置为外键,它们也构成了复合键(主键)。

我的原始ER图来自油漆。

ER Diagram

在EF查询中我需要做的是获取多个数据绑定列绑定到列表视图。

我想要的列是EnumerationCode,Part.Number,Part.Description。

我将使用ProdID(我的产品绑定到DropDown)作为这些附加值的获取器。

所以基本上我要记住从TernaryTable中进行选择T通过EnumCode在ENumTable.EnumID上加入EnumID,其中T.ProdID = myProdID按EnumCode的顺序[从中选择Part.Number,Part.Description从PartID = TernaryTable.PartID的部分中选择)

我认为可能有一个简单的解决方案,该方法是如何获取此数据,然后如何保存对数据的任何更改-但正如我所说的那样,我迷路了。

我需要2种方法,一种用于获取数据,另一种用于保存对数据进行的任何更改。

我已经读过

Get records from table and related related table using Linq to entity

Entity framework linq query Include() multiple children entities

但是似乎我仍然对多重关系迷失了。

编辑

我认为在Haralds出色的答复之后,我需要并且可以发布更好的声明以及真实的图表!

Better SQL Diagram

现在获取表信息:

我想拥有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。

如有需要,我可以发布更多详细信息。

1 个答案:

答案 0 :(得分:1)

我的,这是一个奇怪的多对多对多!

通常会有以下设计:

  • 每个Product的零个或多个Parts,每个Part的零个或多个Products(多对多ProductPart)中使用
  • 每个Product的零个或多个Enumerations,每个Enumeration的零个或多个Products(多对多ProductEnumeration)使用
  • 每个Part的零个或多个Enumerations,每个Enumeration的零个或多个Parts(多对多EnumerationPart)中使用

这将导致三个联结表ProductPartProductEnumerationEnumerationPart

您选择的设计只有一个连接表。

您确实意识到在设计中,Product一旦拥有PartProductPart都具有相同的{{1 }},不是吗?除了Enumeration的{​​{1}}之外,product不能包含更多或其他EnumerationsParts不能与product一起使用,但不能没有Product

如果您真的想将数据库限制在此范围内,则将具有以下类:

Part

您的联结表如下:

Enumerations
  

请注意:在实体框架中,非虚拟属性表示   表中的实际列;虚拟属性代表   表之间的关系

您的DbContext将具有您的四个表:

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; }
}

最后在OnModelCreating中,您必须指定设计:

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; }
}

回到您的问题

  

给出一个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;} } ,并为此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的所有EnumerationCodesPart.NumberPart.Description记录

使用实体框架时,人们倾向于对外键执行联接,而不是在表中使用虚拟属性,从而使事情变得比所需的更为复杂。

如果使用虚拟属性,查询将非常简单直观:

Product

实体框架足够聪明,可以检测到需要哪些联接。

如果您确实要执行联接,则必须对三个表进行联接。这样的连接看起来很可怕:

ProductId

很幸运,您不需要产品的说明。如果您要使用虚拟属性,这将很容易:

var result = dbContext.Junctions
    .Where(junction => junction.ProductId == productId)
    .Select(junction => new
    {
        EnumerationCode = junction.Enumeration.EnumerationCode,
        PartNumber = junction.Part.Number,
        PartDescription = junction.Part.Description,
    });

由您决定编写包含四个表的联接。查看区别并确定从现在开始要使用哪种方法。