加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

实体框架 – MVC 3 EF 4.1 dbContext – 删除具有不可空的外键关

发布时间:2020-12-15 23:40:27 所属栏目:asp.Net 来源:网络整理
导读:我正在使用MVC 3,EF 4.1和dbContext.我需要知道如何使用不可空的外键以一对多关系删除实体. 当我删除子实体并执行SaveChanges我得到错误: 操作失败:无法更改关系,因为一个或多个外键属性不可为空.当对关系进行更改时,将相关的外键属性设置为空值.如果外键
我正在使用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; }
}

}

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; }
}

userContactUserId和userContactTypeId是必需的外键.

在dbContext容器中,Users和UserContact都是DbSet.

我有一个ViewModel的用户和一个ViewModel的UserContact如下

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; }

}

将更改保存到用户配置文件时,我会循环使用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 });
                        }
                    }

我会感谢任何帮助.

解决方法

我设法解决了以下问题:

首先,我可以通过将DbContext(例如“ctx”)转换为IObjectContextAdapter并获取对ObjectContext的引用来获取ObjectContext.

接下来,我简单地称之为DeleteObject方法传递要删除的UserContact记录.

当SaveChanges获取数据库中的删除符合预期时.

if (c.isDeleted == true)  // Deleted UserContact
{
    ObjectContext oc = ((IObjectContextAdapter)ctx).ObjectContext;
    oc.DeleteObject(uc)
}

以下是相关代码片段:

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();

希望这能帮助未来的人.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读