[英]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.