我正在开发一个使用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,并且随着实体的增长和添加更多关联,需要越来越多的黑客攻击。有什么明显的东西我不见了吗?
** 更新 ** 根据Ladislav在下面的回答,我在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) #>)]
<#+
}
}
希望有所帮助!
答案 0 :(得分:1)
听起来您的BillingAddress映射不正确,因为AddressId不会被处理为关系的FK。
尝试将此属性添加到导航属性中:
[ForeignKey("AddressId")]
public Address BillingAddress { get;set; }
如果您首先将EDMX与数据库一起使用,请确保这些类之间存在正确配置的关系。 EF在其商店映射和商店映射中使用此信息定义操作的顺序。如果您没有正确配置的关系,则按类型名称的字母顺序处理实体=&gt;在Account
之前处理Address
。
顺便说一下。您确定Account
来电期间SaveChanges
没有重复吗?