SQL Server 实体框架n对n关系将对象添加到另一个对象

qgelzfjb  于 2022-11-21  发布在  其他
关注(0)|答案(2)|浏览(159)

我有一个客户模型:

public class Client

{
    [Key]
    public int id { get; set; }
    [Required]
    public string? Hostname { get; set; }
    public ICollection<Software>? Softwares { get; set; }

}

和带软件的型号:

public class Software
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int id { get; set; }
        public string Name { get; set; }
        public ICollection<Client>? Clients { get; set; }
    }

这应该是n对n连接。如何向客户端添加软件?
我尝试过的

public async void add(Software software)
        {
            using (var repo = new ClientRepository(contextFactory.CreateDbContext()))
            {
                client.Softwares.Add(software);
                await repo.Save(client);
            }

存储库:

public async Task Save(Client client)
        {
            _context.Clients.Update(client);
            _context.SaveChanges();
        }
        }

这适用于我添加的第一个软件,但如果我尝试添加第二个软件,则会出现以下错误:
SqlException(SQL例外状况):违反PRIMARY KEY条件约束'PK_ClientSoftware'。无法在对象'dbo.ClientSoftware'中插入重复的索引键。重复的索引键值为(7003,5002)。

oiopk7p5

oiopk7p51#

Q:你是不是每次都用new()做一个新的?
答:不,它是一个已经存在的软件。
那就是错误。
第一个SaveChanges()将开始将其作为Existing进行跟踪。您可以检查:Id将为!= 0。
当您稍后将其添加到同一个客户端时,您将收到重复错误。
所以在你的代码中:

await add(software);       // existing
  software = new Software(); // add this

相关,更改:

public async void add(Software software)

public async Task Add(Software software)

永远避免async void

ssgvzors

ssgvzors2#

您似乎正在添加多个相同的关系。在将软件添加到客户端之前,请确保关系尚不存在,然后您可以继续将软件添加到客户端。
同时,你也可以改进你的实体。为主键使用更好的命名,并为Software类添加[Key]属性。
Client

public class Client
{
    public Client()
    {
        Softwares = new HashSet<Software>();
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ClientId { get; set; }
    [Required]
    public string Hostname { get; set; }
    public ICollection<Software> Softwares { get; set; }
}

Software

public class Software
{
    public Software()
    {
        Clients = new HashSet<Client>();
    }
    
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int SoftwareId { get; set; }
    public string Name { get; set; }
    public ICollection<Client> Clients { get; set; }
}

检查关系是否已存在:

// Get the client including its related softwares
var client = dbContext.Clients.Include(x => x.Softwares)
    .FirstOrDefault(x => x.Hostname == "Ibrahim");

if (client != null)
{
    // Check with unique property such as name of software
    // If it does not exist in this current client, then add software
    if (!client.Softwares.Any(x => x.Name == software.Name))
        client.Softwares.Add(software);

    dbContext.SaveChanges();
}

注:如果更新实体,请记住创建新的迁移和数据库。

相关问题