【问题标题】:EF 6.1.3 - Cannot insert duplicate key in objectEF 6.1.3 - 无法在对象中插入重复键
【发布时间】:2015-10-28 14:43:11
【问题描述】:

我在网站上搜索了解决我的问题,但我仍然没有解决它。 我有 2 个实体:

public class Article
{
    [Key]
    public Guid ID { get; set; }
    public Guid? ApprovedBy_ID { get; set; }
    public Guid CreatedBy_ID { get; set; }
    public virtual Profile ApprovedBy { get; set; }
    public virtual Profile CreatedBy { get; set; }
    //New guid for new article
    public Article()
    {
        ID = Guid.NewGuid();
    }
}
public class Profile
{
    [Key]
    public Guid ID { get; set; }
    [Required]
    [StringLength(100)]
    public string FullName { get; set; }
    public Profile()
    {
        ID = Guid.NewGuid();
    }
}

这是我的插入逻辑:

    private readonly iContext context;
    public ArticleLogic()
    {
        context = new iContext();
    }
    public IEnumerable<Article> GetAllArticle()
    {
        return context.Articles.Include("Categories").Include("Pictures").Include("ApprovedBy").Include("CreatedBy").Include("Template");
    }

    public Article AddArticle(Article article)
    {
            try
            {
                Profile pf = context.Profiles.First();
                context.Profiles.Attach(pf);

                Article art = new Article();
                art.Title = article.Title;
                art.Description = article.Description;
                art.Content = article.Content;
                art.Tag = article.Tag;
                art.Template = article.Template;
                //pf has ID = '0816f19c-31c1-4103-8f51-ba422beab1c0' (first row in database)
                art.CreatedBy = pf;
                art.CreatedBy_ID = pf.ID;
                context.Articles.Add(art);
                context.SaveChanges();

                return article;
            }
            catch (Exception ex)
            {
                //But ex throw error duplicate ID = '7aa1d064-54ff-47b9-807d-db422fa71f8c' (second row in database)
                Debug.WriteLine(ex.StackTrace);

                throw ex;
            }

    }

数据库上下文:

public myContext()
    : base("name=abc")
{
    this.Configuration.LazyLoadingEnabled = true;
    this.Configuration.ProxyCreationEnabled = false;
}
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<Template> Templates { get; set; }
public virtual DbSet<Article> Articles { get; set; }
public virtual DbSet<Picture> Pictures { get; set; }
public virtual DbSet<Profile> Profiles { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //One-to-many: Article - Picture (nullable)
    modelBuilder.Entity<Picture>()
        .HasOptional<Article>(c => c.Article)
        .WithMany(p => p.Pictures)
        .HasForeignKey(f => f.ArticleId);

    ////One-to-many: Role - Profile
    modelBuilder.Entity<Profile>()
        .HasRequired<Role>(i => i.Role)
        .WithMany(i => i.Profiles)
        .HasForeignKey(f => f.RoleID);

    ///Many-to-many: Article - Category
    modelBuilder.Entity<Article>()
        .HasMany(t => t.Categories)
        .WithMany(t => t.Articles)
        .Map(m => {
                m.ToTable("ArticleCategories");
                m.MapLeftKey("ArticleId");
                m.MapRightKey("CategoryId");
         });
    //
        modelBuilder.Entity<Article>()
            .HasOptional(a => a.ApprovedBy)
            .WithMany(a => a.ArticleApprovedBy)
            .HasForeignKey(f=>f.ApprovedBy_ID)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Article>()
            .HasRequired(a => a.CreatedBy)
            .WithMany(a => a.ArticleCreatedBy)
            .HasForeignKey(f => f.CreatedBy_ID)
            .WillCascadeOnDelete(false);

        base.OnModelCreating(modelBuilder);
}

我正在使用 CodeFirst EF 6.1.3,但出现错误:违反主键约束“PK_Profiles”。无法像此链接Entity Framework Code First - Cannot insert duplicate key in object 'dbo.T_CRProviders' 一样在对象“dbo.Profiles”中插入重复键? 谁能帮我?谢谢。

【问题讨论】:

  • 您能否发布您用于构建数据库上下文的代码?
  • @ebramtharwat 我更新了我的数据库上下文
  • 您在表格字段中设置了自动生成的Guid(唯一标识符)? GUID 的默认值为00000000...,如果未设置Guid 或表字段未自动生成(newsequentialid()),则每次发送。
  • 可能是因为您没有设置 guid,您最终尝试插入多个具有空 guid 的 guid,以便它们匹配。
  • @PedroFernandesFilho 我在 public Article() { ID = Guid.NewGuid(); }

标签: asp.net entity-framework entity-framework-6


【解决方案1】:

context 认为pf 是新的,应该插入到数据库中。显示context 的实例化和配置 - 你是否禁用了更改跟踪?

【讨论】:

  • 但是我该怎么做呢?我尝试context.Profiles.Attach(pf); context.Entry(pf).State = EntityState.Unchanged; context.Entry(article.CreatedBy).State = EntityState.Unchanged; context.Entry(article.ApprovedBy).State = EntityState.Unchanged;,但它不正确。
  • 您发布的实体/插入代码与您的代码中显示的完全一致吗? Profile 实体与您的模型配置不匹配,显然 EF 认为数据库中不存在 Profile 对象,它应该基于您的代码。此外,禁用代理生成时延迟加载不起作用
  • 关注this,但仍然有错误,很麻烦,对这个问题有什么想法吗? :(
  • 我在问题上添加了更多的插入逻辑代码,我意识到错误会与插入的 ID 产生差异 ID,我不知道为什么会这样。 :D
【解决方案2】:

您需要告诉 EF 一个 Profile 可以被文章多次引用:

modelBuilder.Entity<Article>()
    .HasOptional(a=>a.ApprovedBy)
    .WithMany()
    .WillCascadeOnDelete(false);

modelBuilder.Entity<Article>()
    .HasOptional(a=>a.CreatedBy)
    .WithMany()
    .WillCascadeOnDelete(false);

如果属性是强制性的(在数据库中不是 null),则 HasOptional 也可以是 HasRequired。 如果您希望(如您在示例中所做的那样)能够将配置文件与文章的多个属性(以及多个文章)相关联,则添加 WithMany 是此处的关键。

PS:这段代码是凭记忆写的,有些地方需要调整。

【讨论】:

  • 我添加了这段代码,但没有任何变化,我认为问题是 EF 不知道存在实体。我不知道如何让context 知道配置文件存在。
  • 我想你还是需要它。还必须有别的东西。使用此映射上下文已经知道配置文件,当您执行 First() 时,您会从数据库中获得有效的配置文件,对吗?尝试添加 Guid 属性 ApprovedById 和 CreatedById 并将它们映射为 FK 在我的答案中的映射中(现在在手机上)
  • 是的,你的情况也是如此。它应该工作。我只看到您正在重新附加配置文件。当您从上下文中获取实体时,就像使用配置文件一样,您不必附加它(它已经附加)。
【解决方案3】:

您的线路:

 context.Profiles.Attach(pf);

将附加 pf,但它已被 EF 跟踪。你刚刚从数据库中得到它。 pf 将由 EF 重新插入,但此操作失败。只需删除线,你会没事的。

Add/Attach and Entity States

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 2014-05-04
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多