0

我正在开发一个使用 EF 4.2 和数据库优先开发的应用程序,使用标准 T4 模板生成 DbContext 和 POCO。T4 模板生成如下实体:

public class Address
{
    public int AddressId { get;set; }
    public string Address1 { get;set; }
    public string City { get;set; }
}

public class Account
{
    public int AccountId { get;set; }
    public string Name { get;set; }
    public int AddressId { get;set; }
    public Address BillingAddress { get;set; }
}

当我为现有帐户创建帐单地址时,我的代码如下所示:

public void Save(Account updated)
{
    var existing = DbContext.Find(updated.AccountId);

    MyContext.Entry(existing).CurrentValues.SetEntry(updated);
    existing.Address = updated.Address;

    MyContext.SaveChanges();
}

观察 SQL Server Profiler,我可以看到地址条目被插入到数据库中,但不幸的是,它发生帐户条目更新之后,因此地址与其父帐户分离,当我下次加载帐户时,计费地址又是空的。

一种解决方法是在调用 SaveChanges() 之后添加以下代码:

if (existing.AddressId == null && existing.Address != null)
{
    existing.AddressId = existing.Address.AddressId;
    MyContext.SaveChanges();
}

虽然它可能有效,但需要对数据库进行第二次 SQL UPDATE,并且随着实体的增长和添加更多关联,需要越来越多的 hack。我有什么明显的遗漏吗?

**更新** 在下面 Ladislav 的回答之后,我在我的 T4 模板的 WriteNavigationProperty 中添加了对以下方法的调用:

void WriteKeyAttribute(CodeGenerationTools code, NavigationProperty navigationProperty, MetadataTools ef)
{
    var dependentProperties = navigationProperty.GetDependentProperties();
    if (dependentProperties.Any())
    {
        var keys = new List<string>();
        foreach (var key in dependentProperties)
        {
            keys.Add(String.Format("\"{0}\"", key.Name));
        }
#>
    [ForeignKey(<#= String.Join(", ", keys) #>)]
<#+
    }
}

希望有帮助!

4

1 回答 1

1

听起来您的 BillingAddress 映射不正确,因为 AddressId 未作为关系的 FK 处理。

尝试将此属性添加到您的导航属性:

[ForeignKey("AddressId")]
public Address BillingAddress { get;set; }

如果您将 EDMX 与数据库一起使用,请首先确保这些类之间存在正确配置的关系。EF 在其存储映射中使用此信息,并且存储映射定义了操作的顺序。如果您没有正确配置关系实体,则按其类型名称的字母顺序处理 =>AccountAddress.

顺便提一句。你确定你的通话Account过程中没有重复吗?SaveChanges

于 2012-04-27T08:29:49.033 回答