Linq to SQL 数据上下文未更新外键关系

JCh*_*ian 5 c# foreign-keys linq-to-sql

我正在针对使用 L2S 的存储库编写数据库测试。在我的数据库中,我有一个Manifest实体和一个AllocatedTransaction实体。AllocatedTransaction 实体有一个指向 Manifest id 的外键。DDL 看起来像这样:

Manifest:
Id - int - identity

AllocateTransaction:
Id - int - identity
Quantity - int
ManifestId - FK to Manifest
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我正在检查 AllocatedTransactions 是否与 Manifest 一起返回。测试看起来像这样:

[TestMethod]
public void FindByIdTest()
{
    using (data.EZTracDataContext dataContext = new data.EZTracDataContext())
    {
        using (new TransactionScope())
        {
            data.Manifest manifest = _testDataProvider.AddManifest(dataContext);

            data.AllocatedTransaction allocatedTransaction = _testDataProvider.AddEligibilityAllocated(dataContext, 5, manifest.Id);

            ManifestRepository repository = CreateRepository(dataContext);

            var actual = repository.FindById(manifest.Id).AllocatedTransactions;
            var expected = new[] { new domain.AllocatedTransaction(allocatedTransaction.Id, 5, manifest.Id) }.ToList();

            CollectionAssertAreEqual(actual, expected);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

_testDataProvider刚刚将记录添加到使用在通过数据库dataContext。该FindById方法如下所示:

public domain.Manifest FindById(int id)
{
    var persistedManifest = GetPersistedManifest(id);
    var requestedManifest = GetDomainManifestFromData(persistedManifest);
    return requestedManifest;
}

private Manifest GetPersistedManifest(int manifestId)
{
    return (from manifests in DataContext.Manifests
            where manifests.Id == manifestId
            select manifests).FirstOrDefault();
}
Run Code Online (Sandbox Code Playgroud)

我的问题是从 DataContext 返回的 Manifest 实体没有关联的 AllocateTransaction。奇怪的是,预先存在的 Manifest确实带着它们的 AllocatedTransactions 回来了。使用相同的 DataContext 对象插入记录和检索记录是否会导致这种情况?这是 L2S 的错误吗?

Nei*_* T. 1

如果我理解你的问题,这就是你想要做的吗?

using (new TransactionScope())
{
    Manifest manifest = new Manifest
    {
        AllocatedTransactions.Add(new AllocatedTransaction
        {
            Quantity = 5
        }
    };

    DataContext.Manifests.InsertOnSubmit(manifest);
    DataContext.SubmitChanges();

    Manifest newManifest = DataContext.Manifests.Where(a => a.ID == manifest.ID).SingleOrDefault(); 

    Assert.AreEqual(manifest.AllocatedTransactions.First().Quantity, newManifest.AllocatedTransactions.First().Quantity);
}
Run Code Online (Sandbox Code Playgroud)

您也不需要手动检索与清单关联的 AlulatedTransaction 实体。只需Manifest像我对newManifest对象所做的那样检索实体,所有关联的AllocatedTransaction实体都应该随之而来。

更新:

看起来您试图以错误的方向连接。您需要将 AllocationTransaction 附加到 Manifest,而不是相反:

Manifest manifest = DataContext.Manifests.Single(a => a.ID == 27);
AllocatedTransaction allTrans = DataContext.AllocatedTransactions.Single(a => a.ID == 53);

manifest.AllocatedTransactions.Add(allTrans);
DataContext.SubmitChanges();
Run Code Online (Sandbox Code Playgroud)

这假设 Manifest 和 AlulatedTransaction 记录都已存在。我强烈建议您**不要**预先填充ManifestIDAlulatedTransactions 对象中的字段。如果按照我上面演示的方式添加它,LINQ 引擎将自动解析并更新外键值。如果您提前设置该值,它可能会丢弃 ChangeSet,并假设您正在尝试添加新记录而不是附加现有记录。