简体   繁体   English

通过多列在两个实体之间创建多对多关系

[英]Create many-to-many relationship between two entities via multiple columns

I have the following four tables:我有以下四个表:

Customer顾客

Id
FirstName
...

ConsumptionPoint消费点

Id
Address
...

Invoice发票

Id
InvoiceNumber
CustomerId
ConsumptionPointId
...

ContractAccount合约账户

Id
ContractAccountNumber
CustomerId
ConsumptionPointId
IsCurrentDelivery
...

I want to get the ContractAccountNumber for an Invoice.我想获取发票的 ContractAccountNumber。

Is it possible to create some kind of a relation between these both to access the ContractAccount(s) of an Invoice directly?是否可以在这两者之间创建某种关系以直接访问 Invoice 的 ContractAccount(s)?

Currently I'm doing something like:目前我正在做类似的事情:

invoice.Customer.ContractAccounts
    .Where(ca => ca.ConsumptionPoint == invoice.ConsumptionPoint &&
    ca.IsCurrentDelivery == true).FirstOrDefault();

update in SQL I would simply do a join with multiple conditions:在 SQL 中更新我只会用多个条件进行连接:

SELECT i.Id AS InvoiceId, ca.Id AS ContractAccountId, 
ca.ContractAccountNumber
FROM Invoices i
LEFT JOIN ContractAccounts ca
ON i.ConsumptionPointId = ca.ConsumptionPointId
AND i.CustomerId = ca.CustomerId
WHERE ca.IsCurrentDelivery = 1

update 2:更新2:

Basically I just want to get rid of the ca.ConsumptionPoint == invoice.ConsumptionPoint in the Where-Clause and want to define this inside the relation.基本上我只想摆脱 Where-Clause 中的ca.ConsumptionPoint == invoice.ConsumptionPoint并想在关系中定义它。

Actually this is a many-to-many relationship: one Invoice can link to many ContractAccounts (via different Customer/ConsumptionPoint combinations) and one ContractAccount can link to many Invoices.实际上这是一个多对多的关系:一个 Invoice 可以链接到多个 ContractAccounts(通过不同的 Customer/ConsumptionPoint 组合),一个 ContractAccount 可以链接到多个 Invoice。 Is there no way to tell .net to build a many-to-many relationship, based on the combination of two custom columns?基于两个自定义列的组合,有没有办法告诉 .net 建立多对多关系?

I do not think that you need two keys for that.我不认为你需要两把钥匙。 Using EF core you can create a relationship like that:使用 EF 核心,您可以创建这样的关系:

Invoice:发票:

public class Invoice
{
  public int Id {get; set;}
  public int InvoiceNumber {get; set;}
  public int CustomerId {get; set;}
  public Customer Customer {get; set;}
  public int ConsumptionPointId {get; set;}

  public int ContractAccountId {get; set;}
  public ContractAccount ContractAccount {get; set;}
}
public class ContractAccount
{
  public int Id {get; set;}
  public int ContractAccountNumber {get; set;}
  public bool IsCurrentDelivery {get; set;}
}

Then configuration:然后配置:

modelBuilder.Entity<Invoice>()
  .HasOne(b => b.ContractAccount)
  .WithOne()
  .HasForeignKey<Invoice>(b => b.ContractAccountId);

//probably already exists in your code
modelBuilder.Entity<Invoice>()
  .HasOne(b => b.Customer )
  .WithMany()
  .HasForeignKey(b => b.CustomerId);

And then you can access it directly from invoice: invoice.ContractAccount然后你可以直接从发票访问它: invoice.ContractAccount

After some deeper investigation I have found a solution.经过一些更深入的调查,我找到了解决方案。

Basically it's just a many-to-many relationship.基本上它只是一个多对多的关系。 So we can add the appropriate properties to Invoice and ContractAccount Model:所以我们可以为 Invoice 和 ContractAccount 模型添加适当的属性:

public class Invoice
{
    [Key]
    public long Id { get; set; }
    public Customer Customer { get; set; }
    public ConsumptionPoint ConsumptionPoint { get; set; }
    public virtual ICollection<ContractAccount> ContractAccounts { get; set; }
}

public class ContractAccount
{
    [Key]
    public long Id { get; set; }
    public Customer Customer { get; set; }
    public ConsumptionPoint ConsumptionPoint { get; set; }
    public ICollection<Invoice> Invoices { get; set; }
}

Now, we just have to configure the relationship manually:现在,我们只需要手动配置关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<Invoice>()
        .HasMany(i => i.ContractAccounts)
        .WithOne()
        .HasForeignKey(ca => new { ca.CustomerId, ca.ConsumptionPointId })
        .HasPrincipalKey(i => new { i.CustomerId, i.ConsumptionPointId });
    modelBuilder.Entity<ContractAccount>()
        .HasMany(ca => ca.Invoices)
        .WithOne()
        .HasForeignKey(i => new { i.CustomerId, i.ConsumptionPointId })
        .HasPrincipalKey(ca => new { ca.CustomerId, ca.ConsumptionPointId });
}

And that's it.就是这样。 Now I can do something like:现在我可以做这样的事情:

invoice.ContractAccounts
    .Where(ca => ca.IsCurrentDelivery == true).FirstOrDefault();

which is way better than before.这比以前好多了。

Thanks for your comments, which pointed me to the right direction.感谢您的评论,这为我指明了正确的方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MVC3中相同类型的实体之间的多对多关系 - Many-to-many relationship between entities of same type in MVC3 如何创建多对多关系实体并为它们播种? - How to create Many-to-Many relationship entities and seed them? 使用实体的多对多关系查询 - Many-to-Many relationship query using entities 如何包含多个实体,中间是多对多 - How to include multiple entities with one many-to-many in between 在EF中没有联接表的情况下,如何在具有多对多关系的两个表(实体)之间使用LINQ进行JOIN查询? - How can I make a JOIN query with LINQ between two tables (entities) with many-to-many relationship, while there is no joining table in EF? Linq to Entities使用POCO为多对多关系插入多个子关系记录 - Linq to Entities insert multiple child relationship records for many-to-many relationship using POCO 同一类之间的多对多关系 - Many-to-many relationship between the same class 在模型中创建与自身的多对多关系 - Create a many-to-many relationship in a model to itself 无法创建多对多关系 - Can't create many-to-many relationship 首先如何在代码中定义两个实体之间的多对多和一对多关系? - how to define many-to-many and one-to-many relations between two entities in code first?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM