Max*_*Max 14 entity-framework asp.net-mvc-3
我正在使用MVC 3,EF 4.1和dbContext.我需要知道如何使用不可为空的外键删除一对多关系中的实体.
当我删除子实体并执行SaveChanges时,我收到错误:
操作失败:无法更改关系,因为一个或多个外键属性不可为空.当对关系进行更改时,相关的外键属性将设置为空值.如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象.
从其他帖子中,我了解使用Remove(entity)标记要删除的实体.在SaveChanges期间,EF将外键设置为Null,并发生上述错误.
我发现一些帖子在子实体上使用DeleteObject而不是Remove; 但是,由于添加了dbContext和DbSet,似乎删除了DeleteObject方法.
我发现帖子建议将EDMX外键关系修改为Nullable.修改EDMX很好,但每当完成数据库更新模型时,这些更改都会被修改,必须重新应用.不是最佳的.
另一篇文章建议创建一个外键关系设置为Nullable的代理实体,但我不明白这种方法.它似乎与修改EDMX的问题相同,因为当保存对EDMX的更改时,上下文会自动更新.
我的简化模型是:
public partial class User
{
public User()
{
this.UserContacts = new HashSet<UserContact>();
}
public long userId { get; set; }
public string userEmail { get; set; }
public string userPassword { get; set; }
public string userFirstName { get; set; }
public string userLastName { get; set; }
. . .
public virtual Country Country { get; set; }
public virtual State State { get; set; }
public virtual ICollection<UserContact> UserContacts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
}
public partial class UserContact
{
public long userContactId { get; set; }
public long userContactUserId { get; set; }
public long userContactTypeId { get; set; }
public string userContactData { get; set; }
public virtual ContactType ContactType { get; set; }
public virtual User User { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
userContactUserId和userContactTypeId是必需的外键.
在dbContext容器中,Users和UserContact都是DbSet.
我有一个用户的ViewModel和一个UserContact的ViewModel,如下所示
public class UserContactViewModel
{
[HiddenInput]
public long UserContactId { get; set; }
[HiddenInput]
public long UserContactUserId { get; set; }
[Display(Name = "Contact")]
[Required]
public string ContactData { get; set; }
[Required]
public long ContactType { get; set; }
[HiddenInput]
public bool isDeleted { get; set; }
}
public class MyProfileViewModel
{
[HiddenInput]
public long UserId { get; set; }
[Required]
[Display(Name = "First Name")]
[StringLength(100)]
public string FirstName { get; set; }
[Required]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
....
public IEnumerable<UserContactViewModel> Contacts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
保存对用户配置文件的更改时,我遍历UserContactViewModel实体列表以确定已添加,修改或删除的实体.
foreach (var c in model.Contacts)
{
UserContact uc = usr.UserContacts.Single(con => con.userContactId == c.UserContactId);
if (uc != null)
{
if (c.isDeleted == true) // Deleted UserContact
{
ctx.UserContacts.Remove(uc); // Remove doesn't work
}
else // Modified UserContact
{
uc.userContactData = c.ContactData;
uc.userContactTypeId = c.ContactType;
ctx.Entry(uc).State = EntityState.Modified;
}
}
else // New UserContact
{
usr.UserContacts.Add(new UserContact { userContactUserId = model.UserId, userContactData = c.ContactData, userContactTypeId = c.ContactType });
}
}
Run Code Online (Sandbox Code Playgroud)
我很感激任何帮助.
Max*_*Max 15
我设法解决了以下问题:
首先,我能够通过将我的DbContext(例如"ctx")转换为IObjectContextAdapter来获取ObjectContext,然后获取对ObjectContext的引用.
接下来,我简单地调用DeleteObject方法传递要删除的UserContact记录.
当SaveChanges获取数据库中的删除按预期发生时.
if (c.isDeleted == true) // Deleted UserContact
{
ObjectContext oc = ((IObjectContextAdapter)ctx).ObjectContext;
oc.DeleteObject(uc)
}
Run Code Online (Sandbox Code Playgroud)
以下是相关代码的片段:
foreach (var c in model.Contacts)
{
UserContact uc = null;
if (c.UserContactId != 0)
{
uc = ctx.UserContacts.Find(c.UserContactId);
}
if (uc != null)
{
if (c.isDeleted == true) // Deleted UserContact
{
ObjectContext oc = ((IObjectContextAdapter)ctx).ObjectContext;
oc.DeleteObject(uc);
}
else // Modified UserContact
{
uc.userContactData = c.ContactData;
uc.userContactTypeId = c.ContactType;
ctx.Entry(uc).State = EntityState.Modified;
}
}
else // New UserContact
{
usr.UserContacts.Add(new UserContact { userContactData = c.ContactData, userContactTypeId = c.ContactType });
}
}
ctx.Entry(usr).State = EntityState.Modified;
ctx.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
希望这有助于将来的某些人.