使用实体框架更新数据库中的模型与外键冲突

时间:2012-12-28 21:32:15

标签: sql-server asp.net-mvc entity-framework

我知道这已被问过数百万次,而且我已经有数百次这样做了,但由于某些原因我无法解决这个问题。

我得到众所周知的错误:

The UPDATE statement conflicted with the FOREIGN KEY constraint ...

完成插入或删除后,我的数据库中的所有表都会级联。

现在出现错误: 我想更新链接到culture表(对于语言)的管理员表(管理员帐户)。

一切都正确填写。因此我们得到以下代码:

    [HttpPost]
    public ActionResult Edit(Admins admins)
    {
        if (!ModelState.IsValid)
        {
            return View(admins);
        }
        admins.cultures_id = admins.Cultures.id;
        _unitOfWork.AdminsRepository.Update(admins);
        _unitOfWork.Save();

        return RedirectToAction("Index", "Overview", new { area = "Admin" });
    }

我首先将我的管理对象/实体的文化ID设置为与链接的culture表中的id的文化ID相同:

admins.cultures_id = admins.Cultures.id;

然后我填写更新表:

_unitOfWork.AdminsRepository.Update(管理员);

方法更新包含以下代码:

    public virtual void Update(TEntity entityToUpdate)
    {
        DbSet.Attach(entityToUpdate);
        ArtWebShopEntity.Entry(entityToUpdate).State = EntityState.Modified;
    }

到目前为止一直很好,但是,当我真的想要保存管理员时:

_unitOfWork.Save();

该save方法包含以下代码:

        public void Save() {
        try
        {
            _artWebshopEntity.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", validationErrors.Entry.Entity.GetType().Name, validationErrors.Entry.State);

                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"", validationError.PropertyName, validationError.ErrorMessage);
                }
            }

            throw;  // Will do something here later on...
        }

    }

在SaveCHanges方法中,我收到错误。我知道这意味着什么,但我似乎无法解决它。我已经尝试了所有可能导致它的事情。

修改

我只想更新管理员值,因此我不想更新文化值。

这是查询:

update [dbo].[Admins]
set    [login] = 'Herve' /* @0 */,
       [password] = null,
       [salt] = null,
       [email] = 'xxxxx.xxx@glevin.be' /* @1 */,
       [permissions] = 'administrator' /* @2 */,
       [attempts] = 4 /* @3 */,
       [locked] = 0 /* @4 */,
       [cultures_id] = 0 /* @5 */
where  ([id] = 1 /* @6 */)

所以,cultures_id就是问题所在。我现在做了以下事情:

        var updateAdmin = new Admins
            {
                attempts = admins.attempts,
                cultures_id = admins.cultures_id,
                email = admins.email,
                locked = admins.locked,
                login = admins.login,
                id = admins.id,
                password = admins.password,
                permissions = admins.permissions,
                salt = admins.salt,
            };

这样可行,但是当我将Cultures对象添加到混合中时,它会崩溃并给出引用错误。所以它归结为,如何将带有外键的表更新到另一个表的frack还需要更新

编辑II

我的管理员和文化实体(数据库第一),也是sql management studio中数据库的图像:

管理员课程:

public partial class Admins
{
    public int id { get; set; }
    public string login { get; set; }
    public string password { get; set; }
    public string salt { get; set; }
    public string email { get; set; }
    public string permissions { get; set; }
    public Nullable<int> attempts { get; set; }
    public Nullable<bool> locked { get; set; }
    public Nullable<int> cultures_id { get; set; }

    public virtual Cultures Cultures { get; set; }
}

文化课:

public partial class Cultures
{
    public Cultures()
    {
        this.Categories_local = new HashSet<Categories_local>();
        this.Menu_items_local = new HashSet<Menu_items_local>();
        this.Products_local = new HashSet<Products_local>();
        this.Subcategories_local = new HashSet<Subcategories_local>();
        this.Webpages_local = new HashSet<Webpages_local>();
        this.Admins = new HashSet<Admins>();
    }

    public int id { get; set; }
    public string name { get; set; }
    public string display_name { get; set; }

    public virtual ICollection<Categories_local> Categories_local { get; set; }
    public virtual ICollection<Menu_items_local> Menu_items_local { get; set; }
    public virtual ICollection<Products_local> Products_local { get; set; }
    public virtual ICollection<Subcategories_local> Subcategories_local { get; set; }
    public virtual ICollection<Webpages_local> Webpages_local { get; set; }
    public virtual ICollection<Admins> Admins { get; set; }
}

database design

1 个答案:

答案 0 :(得分:0)

我已经开始工作了!

问题在于,在编辑页面中,最后一个字段是显示与管理员ID相对应的文化名称的字段。

换句话说,我做了以下事情:

@Html.EditorFor(model => model.Cultures.name)

但这不是正确的方法。

为了显示文化的名称,但在代码中传递了文化ID,我使用了@ Html.DropDownListFor() - 元素。

然而,问题是我的原始模型 Admins 没有可以传递给我视图中的dropdownlist元素的IEnumerable对象。我必须创建一个名为 CreateAdminModel 的新模型,新模型如下所示:

public class CreateAdminModel
{
    public CreateAdminModel() { }

    public CreateAdminModel(IEnumerable<SelectListItem> cultures) { Cultures = cultures; }

    public CreateAdminModel(Admins admin) { Admin = admin; }

    public CreateAdminModel(IEnumerable<SelectListItem> cultures, Admins admin)
    {
        Cultures = cultures;
        Admin = admin;
    }

    public IEnumerable<SelectListItem> Cultures { get;  set; }
    public Admins Admin { get; internal set; }
}

它有一个由实体框架(数据库优先)创建的Admin对象。

使用该新模型,我创建了以下方法:

    private CreateAdminModel CreateAdminWithcultureDetails(Admins admin = null)
    {
        var cultureItems = (_unitOfWork.CulturesRepository.Get()).ToArray();
        var cultureList = new List<SelectListItem>();
        for (int i = 0; i < cultureItems.Count(); i++) cultureList.Add(new SelectListItem { Text = cultureItems[i].name, Value = cultureItems[i].id.ToString() });

        return admin != null ? new CreateAdminModel(cultureList, admin) : new CreateAdminModel(cultureList);
    }

这会根据文化填充下拉列表,并根据是否传递了管理对象,还会添加管理对象。

现在我可以在视图中使用此模型,并在必要时正确填写下拉列表和管理员。

我将对其他必须使用CRUD的事情做同样的事情。