EF有很多可选
本文关键字:EF | 更新日期: 2023-09-27 18:29:06
我有一个问题,我无法通过谷歌或在stackoverflow上搜索来解决。
我有两个表JournalLines和Accounts,我想引用日记行中的一个帐户(我讨厌经济学),但引用必须是可选的,并且account不应该有任何指向journalline的导航属性(理想情况下)。
JournalLine:
public class JournalLine : Entity<int>
{
public int? Account_Id { get; set; }
public string Desc { get; set; }
public decimal Credit { get; set; }
public decimal Debit { get; set; }
public virtual Account Account { get; set; }
}
_账户:
public class Account : Entity<int>
{
public string Accid { get; set; }
public string Desc { get; set; }
public int VatcodeId { get; set; }
}
以及各自的映射:
public class JournalLineMap : EntityTypeConfiguration<JournalLine>
{
public JournalLineMap()
{
HasKey(k => new { k.Id, k.Account_Id });
Property(k => k.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
ToTable("attJournalLines");
HasEntitySetName("JournalLines");
HasOptional(jl => jl.Account)
.WithMany()
.HasForeignKey(jl => jl.Account_Id);
}
}
public class AccountMap : EntityTypeConfiguration<Account>
{
public AccountMap()
{
ToTable("attAccounts");
HasEntitySetName("Accounts");
}
}
我得到的错误是:
在模型生成过程中检测到一个或多个验证错误:
tSystem.Data.Entity.Edm.EdmAssociationType::多重性与引用冲突>关系"JournalLine_Account"中角色"JournalLine_Account_Target"中的约束>由于Dependent Role中的所有属性都不可为null,因此>主体角色必须为"1"。
这让我很困惑,我希望有人能澄清这个问题。
更新
谢谢你的回答,它在路上帮助了我,我通过拔下钥匙获得了工作关系。然后,当将Account
分配给JournalLine
时,我得到了一个更糟糕的行为——创建了一个重复的帐户。事实证明,这并不是什么奇怪的行为,因为我使用了带有依赖注入的Repository模式。我没有想到的是,两个存储库中的上下文不一样,所以JournalLinesReserve没有跟踪我从自己的存储库中提取的帐户,因此认为将其作为新实体插入是明智的。这是通过在存储库中注入相同的上下文来解决的,这样项目跟踪就可以按预期工作。再次感谢你的帮助。
Ohlin的答案正确地确定了问题——不能有一个具有可为null列的复合主键。这就提出了一些关于你试图建模的问题。
除了主键之外,您的模型似乎可以工作。事实上,我认为只要删除HasKey(k => new { k.Id, k.Account_Id });
就能让事情正常进行。如果你这样做,那么每个JournalLine
都将有自己唯一的ID,并且可以选择与Account
相关。
这将导致以下数据:
| AccountId | Desc |
| 123456789 | Some Account |
| JournalId | AccountId | Description | Credit | Debit |
| 1 | null | Some Tx | 100.00 | 0.0 |
| 2 | 123456789 | Another Tx | 0.0 | 50.0 |
| 3 | 123456789 | MoreTx | 10.00 | 0.0 |
另一方面,如果您在JournalLine
密钥中使用AccountId
的原因是暗示每个帐户实际上都有自己的Journal(从我的account类中听起来有点熟悉),那么您的建模需要一些调整——或者您可能需要一个特殊的"未分类"帐户,专门用于处理未应用于特定帐户的事务。
通过查看您的代码,"感觉"HasKey(k => new { k.Id, k.Account_Id });
可能是造成问题的原因,因为Account_Id
是可以为null的,并且通常不被接受为键。尝试删除Account_Id的可为null的标志,看看会发生什么。
编辑:EF中的键
一个键在其组合中总是需要唯一的(如果您有多个列和键)。这就是为什么不能允许键参数为null值的基本规则。
当您将Account_Id指定为外键时,您已经为其添加了一个密钥,那么为什么还要将其作为主键呢?特别是既然你允许它为空?