通过多列在两个实体之间创建多对多关系
Create many-to-many relationship between two entities via multiple columns
我有以下四个表:
客户
Id
FirstName
...
消费点数
Id
Address
...
发票
Id
InvoiceNumber
CustomerId
ConsumptionPointId
...
合约账户
Id
ContractAccountNumber
CustomerId
ConsumptionPointId
IsCurrentDelivery
...
我想获取发票的 ContractAccountNumber。
是否可以在这两者之间创建某种关系以直接访问发票的 ContractAccount?
目前我正在做类似的事情:
invoice.Customer.ContractAccounts
.Where(ca => ca.ConsumptionPoint == invoice.ConsumptionPoint &&
ca.IsCurrentDelivery == true).FirstOrDefault();
update in 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
更新 2:
基本上我只想去掉 Where 子句中的 ca.ConsumptionPoint == invoice.ConsumptionPoint
并想在关系中定义它。
实际上这是一个多对多关系:一个发票可以 link 到多个 ContractAccount(通过不同的 Customer/ConsumptionPoint 组合),一个 ContractAccount 可以 link 到多个发票。有没有办法告诉 .net 建立多对多关系,基于两个自定义列的组合?
我认为您不需要两把钥匙。使用 EF 核心,您可以创建这样的关系:
发票:
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;}
}
然后配置:
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);
然后您可以直接从发票中访问它:invoice.ContractAccount
经过更深入的调查,我找到了解决方案。
基本上就是多对多的关系。因此我们可以将适当的属性添加到 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; }
}
现在,我们只需手动配置关系:
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 });
}
就是这样。现在我可以做类似的事情:
invoice.ContractAccounts
.Where(ca => ca.IsCurrentDelivery == true).FirstOrDefault();
比以前好多了。
感谢您的评论,为我指明了正确的方向。
我有以下四个表:
客户
Id
FirstName
...
消费点数
Id
Address
...
发票
Id
InvoiceNumber
CustomerId
ConsumptionPointId
...
合约账户
Id
ContractAccountNumber
CustomerId
ConsumptionPointId
IsCurrentDelivery
...
我想获取发票的 ContractAccountNumber。
是否可以在这两者之间创建某种关系以直接访问发票的 ContractAccount?
目前我正在做类似的事情:
invoice.Customer.ContractAccounts
.Where(ca => ca.ConsumptionPoint == invoice.ConsumptionPoint &&
ca.IsCurrentDelivery == true).FirstOrDefault();
update in 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
更新 2:
基本上我只想去掉 Where 子句中的 ca.ConsumptionPoint == invoice.ConsumptionPoint
并想在关系中定义它。
实际上这是一个多对多关系:一个发票可以 link 到多个 ContractAccount(通过不同的 Customer/ConsumptionPoint 组合),一个 ContractAccount 可以 link 到多个发票。有没有办法告诉 .net 建立多对多关系,基于两个自定义列的组合?
我认为您不需要两把钥匙。使用 EF 核心,您可以创建这样的关系:
发票:
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;}
}
然后配置:
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);
然后您可以直接从发票中访问它:invoice.ContractAccount
经过更深入的调查,我找到了解决方案。
基本上就是多对多的关系。因此我们可以将适当的属性添加到 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; }
}
现在,我们只需手动配置关系:
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 });
}
就是这样。现在我可以做类似的事情:
invoice.ContractAccounts
.Where(ca => ca.IsCurrentDelivery == true).FirstOrDefault();
比以前好多了。
感谢您的评论,为我指明了正确的方向。