实体框架多对多关系保存导致错误

时间:2016-10-03 17:17:47

标签: c# sql-server entity-framework

我查看了各种SO问题,但找不到与我的情况类似的问题。我有以下EF模型生成的类

public partial class Resource
{
    public Resource()
    {
         this.Roles = new HashSet<Role>();
    }

    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Role> Roles { get; set; }
}

public partial class Role
{
    public Role()
    {
        this.Resources = new HashSet<Resource>();
        this.Users = new HashSet<User>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<bool> Active { get; set; }

    public virtual ICollection<Resource> Resources { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

public aysnc Task<int> SaveRelationship(params)
{
     var db = GetContext();
     var role = await db.Roles.FirstOrDefaultAsync(...);
     var resource = await db.Resources.FirstOrDefaultAsync(...);
     role.Resources.Add(resource);
     //tried these one at a time as well as together
     resource.Roles.Add(role);
     return await db.SaveChangesAsync();
}

我收到INSERT语句与FOREIGN KEY约束冲突的错误..

它生成/执行的SQL查询是:我知道这个语句不会运行,我可以更改什么,以便生成正确的语句?

exec sp_executesql N'INSERT [Config].[RoleResourceAllocations]([RoleId])
VALUES (@0)
SELECT [ResourceId]
FROM [Config].[RoleResourceAllocations]
WHERE @@ROWCOUNT > 0 AND [ResourceId] = scope_identity() AND [RoleId] = @0',N'@0 int',@0=1

这是我的表

CREATE TABLE [Config].[RoleResourceAllocations]
(
    [ResourceId] [int] IDENTITY(1,1) NOT NULL,
    [RoleId] [int] not null, 

    CONSTRAINT [FK_RoleResourceAllocations_Roles] 
        FOREIGN KEY ([RoleId]) REFERENCES [Identity].[Roles]([Id]),
    CONSTRAINT [FK_RoleResourceAllocations_Resources] 
        FOREIGN KEY ([ResourceId]) REFERENCES [Config].[Resources]([Id]), 
    CONSTRAINT [PK_RoleResourceAllocations] 
        PRIMARY KEY ([RoleId], [ResourceId])
)

2 个答案:

答案 0 :(得分:0)

如果您尝试同时编写新角色和新资源,并且两个表都有外键约束,则每次都会抛出错误,因为数据库中的外键尚不存在(至少使用Oracle)。

有一种解决方法:将第一项写入外键列中的null,然后使用第一项中的键写入第二项。最后使用第二项中的密钥更新第一项。

您可以考虑更改应用程序的设计以避免这种情况。

答案 1 :(得分:0)

这是一个典型的设置,所以你不应该有任何问题。

  

[配置] [RoleResourceAllocations] .ResourceId

应该是一个标识列,因为您从

中获取了该值
  

[配置] [资源]。[ID]

列。

我的另一个建议是将其作为同步工作,然后使用异步内容进行处理。