简体   繁体   English

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

[英]Entity Framework DbUpdateException when storing m:n relationship

I'm having troubles with creating and/or storing m:n relationship with EF 4.3 Code first 我在使用EF 4.3代码创建和/或存储m:n关系时遇到麻烦

So the first entity Publication is defined as with some other internal scalar properties: 因此,第一个实体Publication被定义为具有其他一些内部标量属性:

    public class Publication : IDataErrorInfo{

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

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

and the other class in the same way: 和另一个类以相同的方式:

    public class Group : IDataErrorInfo {

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

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

which according to numerous articles should be fine. 根据许多文章,这应该没问题。

There are several problems I occur. 我发生了几个问题。 AT first: 首先:

  • If I create a new publication and assert it some Groups. 如果我创建一个新出版物并声明某些组。 All is stored to the db. 全部存储到数据库。 But then I restart the program, the same particular publication has ICollection set to null. 但是,然后我重新启动程序,同一特定出版物将ICollection设置为null。 Therefore the information about relationship with Group has been deleted.I don't know why :( 因此,有关与组的关系的信息已被删除。我不知道为什么:(
  • When I try to update exisiting Publication entry with Group relationship, the DBUpdateException is thrown with the following text: 当我尝试使用组关系更新现有的发布条目时,将引发DBUpdateException并显示以下文本:

An error occurred while saving entities that do not expose foreign key properties for their relationships. 保存不公开外键属性为其关系的实体时发生错误。 The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. EntityEntries属性将返回null,因为无法将单个实体标识为异常的来源。 Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types 通过在实体类型中公开外键属性,可以简化保存时的异常处理

In the inner exception is the same, and in the inner exception of this one is the following: 内部例外是相同的,而内部例外是以下内容:

Violation of PRIMARY KEY constraint 'PK_ Publicat _3AF5D6A10AD2A005'. 违反主键约束'PK_ Publicat _3AF5D6A10AD2A005'。 Cannot insert duplicate key in object 'dbo.PublicationGroups'. 无法在对象“ dbo.PublicationGroups”中插入重复键。 The statement has been terminated. 该语句已终止。

I'm asserting the the new values of the Publication as follows: 我宣称该出版物的新价值如下:

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

where publKey is the key of the edited entity and groupKeys is the List of GroupId which should be the publication be related to. 其中publKey是已编辑实体的键, groupKeys是应该与发布相关的GroupId的列表。

after calling db.SaveContext() the exception is thrown 调用db.SaveContext() ,将引发异常

This topic has been covered by numerous articles, but I didn't find any solution. 许多文章讨论了该主题,但是我没有找到任何解决方案。 All of the examples are using the same code, but apparently I'm missing something. 所有示例都使用相同的代码,但是显然我缺少了一些东西。 I'm using SQL Ce 4.0 as the persistance data storage. 我正在使用SQL Ce 4.0作为持久性数据存储。

Thank you guys for answer, I'm dealing with it since yesterday, but don't why this happens 谢谢你们的回答,我从昨天开始就在处理这个问题,但不要为什么会这样

Are you calling .Save after you've added the groups to the database? 将组添加到数据库后,您要致电.Save吗? Otherwise when you try to add the groups to the publication, they won't actually be in the DbSet yet. 否则,当您尝试将组添加到发布中时,它们实际上实际上将不在DbSet中。 The following code works for me - perhaps you could clarify how it differs from yours? 以下代码对我有用-也许您可以阐明它与您的代码有何不同?

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

(Code Updated to use SqlCe provider) (代码已更新为使用SqlCe提供程序)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM