MVC 3 EF 4.1的DbContext - 删除一到多的数据与非空的外键关系对象 [英] MVC 3 EF 4.1 dbContext - Deleting one-to-many data object with non-nullable foreign-key relation

查看:122
本文介绍了MVC 3 EF 4.1的DbContext - 删除一到多的数据与非空的外键关系对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用MVC 3,EF 4.1和的DbContext。我需要知道如何删除一个实体在一个一对多的关系与非空的外键。

I am using MVC 3, EF 4.1, and dbContext. I need to know how to delete an entity in one-to-many relation with a non-nullable foreign-key.

当我删除子实体和执行的SaveChanges我得到的错误:

When I Remove the child entity and execute SaveChanges I get the error:

操作失败:关系不能被改变,因为一个或多个外键的属性是不可为空。当一个变化是有关系提出,相关外键属性设置为空值。如果外键不支持空值,一种新的关系必须定义,外键属性必须指定一个非空值,或者无关的对象必须被删除。

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

从其他职位,据我所知,使用删除(实体),标志着实体删除。在调用SaveChanges,EF设置外键为NULL,并发生上述错误。

From other posts, I understand that using Remove(entity) marks the entity for delete. During SaveChanges, EF sets the the foreign-key to Null and the above error occurs.

我已经发现了一些职位,对子实体使用DeleteObject的,而不是删除;然而,DeleteObject的方法似乎是因为除了和的DbContext的DbSet已被删除。

I have found some posts that use DeleteObject on the child entity rather than Remove; however, the DeleteObject approach seems to have been dropped because of addition to dbContext and DbSet.

我发现,建议修改EDMX外键关系为可以为空的职位。修改EDMX是好的,但每当数据库中的更新模型完成后,这些变化得到核爆,必须重新应用。不是最佳的。

I have found posts that suggest modifying the EDMX foreign-key relation to be Nullable. Modifying the EDMX is fine, but whenever an Update Model for Database is done, these changes get nuked and must be reapplied. Not optimal.

另一篇文章建议设立设置为可空外键关系的代理机构,但我不明白的做法。这似乎从同一个问题遭受在于:当被保存到EDMX变化的背景下得到自动更新修改EDMX。

Another post suggested creating a proxy entity with the foreign-key relations set to Nullable but I do not understand that approach. It seems to suffer from the same issue as modifying the EDMX in that the context gets automatically updated when changes to the EDMX are saved.

我的简化模型是:

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需要外国键。

The userContactUserId and userContactTypeId are required foreign-keys.

在的DbContext容器用户和UserContact是DbSet。

In the dbContext container both Users and UserContact are DbSet.

我有一个视图模型为用户和UserContact一个ViewModel如下:

I have a ViewModel for the User and a ViewModel for UserContact as follows

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实体名单,以确定哪些已被添加,修改或删除。

When saving changes to the user profile, I loop over the list of UserContactViewModel entities to determine which have been added, modified, or deleted.

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

我想AP preciate任何帮助。

I'd appreciate any help.

推荐答案

我设法解决这个问题如下:

I managed to solve the problem as follows:

首先,我可以通过我的铸造的DbContext(如CTX),以一个IObjectContextAdapter,然后获得参考的ObjectContext来获取ObjectContext的。

First, I was able to fetch the ObjectContext by casting my DbContext (eg "ctx") to an IObjectContextAdapter and then obtaining reference to the ObjectContext.

接下来,我简单地称为DeleteObject方法传递UserContact记录被删除。

Next, I simply called the DeleteObject method passing the UserContact record to be deleted.

当调用SaveChanges获取数据库中删除发生的预期。

When SaveChanges gets the deletes in the database happen as expected.

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

下面是相关code的一个片段:

Here is a snippet of the relevant code:

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

希望这可以帮助别人的未来。

Hope this helps someone in future.

这篇关于MVC 3 EF 4.1的DbContext - 删除一到多的数据与非空的外键关系对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆