存储m:n关系时的实体框架DbUpdateException

时间:2012-05-19 08:36:37

标签: c# entity-framework ef-code-first

我遇到了与EF 4.3 Code first创建和/或存储m:n关系的麻烦

因此第一个实体Publication被定义为一些其他内部标量属性:

    public class Publication : IDataErrorInfo{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int PublicationId { get; set; }

    [InverseProperty("Publications")]
    public virtual ICollection<Group> Groups { get; set; }

和另一个类以同样的方式:

    public class Group : IDataErrorInfo {

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int GroupId { get; set; }

    [InverseProperty("Groups")]
    public ICollection<Publication> Publications { get; set; }

根据众多文章应该没问题。

我发生了几个问题。首先:

  • 如果我创建一个新的出版物并断言一些群组。全部存储到数据库中。但后来我重新启动程序,相同的特定发布将ICollection设置为null。因此,有关与集团关系的信息已被删除。我不知道原因:(
  • 当我尝试使用组关系更新现有的Publication条目时,将抛出DBUpdateException并显示以下文本:
  

保存不公开其关系的外键属性的实体时发生错误。 EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更容易地在保存时处理异常

在内部异常中是相同的,并且在此内部异常中如下:

  

违反PRIMARY KEY约束'PK_ Publicat _3AF5D6A10AD2A005'。无法在对象'dbo.PublicationGroups'中插入重复键。   声明已经终止。

我宣称出版物的新价值如下:

var entry = db.Publications.First(a => a.PublicationId == publKey);
entry.Groups = db.Groups.
                Where(a => groupKeys.Contains(a.GroupId)).
                Select(b => b).
                ToList();

其中publKey是已编辑实体的关键,groupKeys是GroupId的列表,该列表应与出版物相关。

调用db.SaveContext()后抛出异常

许多文章都涵盖了这个主题,但我找不到任何解决方案。所有的例子都使用相同的代码,但显然我遗漏了一些东西。我正在使用SQL Ce 4.0作为持久性数据存储。

谢谢大家的回答,我从昨天开始处理它,但不要为什么会这样呢

1 个答案:

答案 0 :(得分:0)

您是否在将数据库添加到数据库后保存?保存?否则,当您尝试将组添加到发布时,它们实际上不会在DbSet中。以下代码对我有用 - 也许您可以澄清它与您的不同之处?

public class Publication
{
    public int PublicationId { get; set; }
    public string PublicationName { get; set; }
    public virtual ICollection<Group> Groups { get; set; }
}

public class Group
{
    public int GroupId { get; set; }
    public string GroupName { get; set; }
    public ICollection<Publication> Publications { get; set; }
}

public class Context : DbContext
{
    public DbSet<Publication> Publications { get; set; }
    public DbSet<Group> Groups { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context>());

        Context context = new Context();

        // Only add the groups if it's a new database
        if (!context.Groups.Any())
        {
            context.Groups.Add(new Group { GroupName = "Group 1" });
            context.Groups.Add(new Group { GroupName = "Group 2" });
            context.SaveChanges();
        }

        if (context.Publications.Any())
        {
            Console.WriteLine("At startup, P1 is in groups " + String.Join(", ", context.Publications.First().Groups.Select(g => g.GroupName)));
        }

        // Add publication
        Publication p;
        p = new Publication();
        p.Groups = context.Groups.ToList();     // Add to all existing groups
        context.Publications.Add(p);
        context.SaveChanges();

        Console.WriteLine("P1 is in groups " + String.Join(", ", context.Publications.First().Groups.Select(g => g.GroupName)));
    }
}

(代码更新为使用SqlCe提供程序)