0

我有一个我无法通过谷歌或在 stackoverflow 上搜索解决的问题。

我有两个表 JournalLines 和 Accounts,我想在日记中引用一个帐户(我讨厌经济学),但引用必须是可选的,并且 Account 不应该对 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”中的引用>约束冲突。>因为从属角色中的所有属性都不可为空,所以 >Principal Role 的多重性必须为“1”。

这让我很困惑,我希望有人能阐明这个问题。

更新

感谢您在路上帮助我的答案,我通过移除钥匙获得了工作关系。然后,在创建重复帐户时,我得到Account了一个奇怪的行为。JournalLine事实证明,这并不是那么奇怪的行为,因为我使用了带有依赖注入的存储库模式。我没有想到的是两个存储库中的上下文并不相同,因此 JournalLinesRepository 没有跟踪我从自己的存储库中获取的帐户,因此认为将其作为新实体插入是明智的。这是通过在存储库中注入相同的上下文来解决的,因此项目跟踪可以按预期工作。再次感谢您的帮助。

4

2 回答 2

3

通过查看您的代码,它“感觉”HasKey(k => new { k.Id, k.Account_Id });可能会导致问题,因为它可以Account_Id为空并且通常不被接受为键。尝试删除 Account_Id 的可为空标志,看看会发生什么。

编辑:EF 中的键

一个键在其组合中始终需要是唯一的(如果您有多个列和键)。这就是为什么您不能允许关键参数为空值的基本规则。

当您将 Account_Id 指定为进一步向下的外键时,您已经为 Account_Id 添加了一个键,那么为什么还要将它作为主键呢?特别是因为您允许它为空?

于 2013-08-27T13:34:43.897 回答
3

Ohlin's Answer正确地识别了这个问题——你不能有一个可以为空的列的复合主键。这引发了一些关于您尝试建模的问题。

除了主键之外,您的模型似乎也可以工作。事实上,我认为仅仅删除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 |

另一方面,如果您AccountIdJournalLine密钥中包含一个的原因是暗示每个帐户实际上都有自己的日志(这在我的帐户类中听起来有点熟悉),那么您的建模需要一些调整——或者您可能需要一个特殊的“未分类”帐户专门用于处理未应用于特定帐户的交易。

于 2013-08-27T14:04:24.140 回答