在EF Core

时间:2017-08-12 19:22:40

标签: c# entity-framework asp.net-core entity-framework-core

我有两张表ClientClientSecret。表格具有以下结构:

public class Client
    {
        public int Id { get; set; }
        public string ClientId { get; set; }
        public string ClientName { get; set; }
    public List<ClientSecret> ClientSecrets { get; set; }
    }

public class ClientSecret
{
        public int Id { get; set; }
        public string Description { get; set; }
        public string Value { get; set; }
        public DateTime? Expiration { get; set; }
        public Client Client { get; set; }
}

我需要创建一个新的Client设置ClientIdClientName并从数据库中获取此对象的新Id

我试过这个(_dbContext通过构造函数中的DI系统获取):

var newClient = new Client();
newClient.ClientName = client.ClientName;
newClient.ClientId = client.ClientId;
_dbContext.Clients.Add(newClient);
await _dbContext.SaveChangesAsync();

var newClientId = newClient.Id;
var clientToUpdate = await _dbContext.Clients.Where(x => x.Id == newClientId).SingleOrDefaultAsync();

clientToUpdate.ClientSecrets.AddRange(secrets);
_dbContext.Clients.Update(clientToUpdate);
await _dbContext.SaveChangesAsync();

首先我需要创建一个Client,因为表ClientSecrets需要ClientId才能在此表中创建新记录。

我收到此错误消息:

使用以下内容排除错误:_dbContext.Clients.Update(clientToUpdate);

  

InvalidOperationException:实体类型'Client'的实例不能   被跟踪,因为具有相同密钥的此类型的另一个实例是   已被跟踪。添加新实体时,对于大多数关键类型a   如果没有设置密钥,则将创建唯一的临时密钥值(即,如果   key属性被赋予其类型的默认值)。如果你   明确设置新实体的关键值,确保不这样做   与现有实体或为其他实体生成的临时值发生冲突   新实体。附加现有实体时,请确保只有一个实体   具有给定键值的实体实例附加到上下文。

如何解决此问题?

3 个答案:

答案 0 :(得分:5)

  

实体类型的实例&#39;客户&#39;无法跟踪,因为另一个   已经跟踪了具有相同密钥的此类型的实例

client已创建_dbContext.Clients.Add(newClient);个实例。

您需要在附加更新的条目之前分离第一个条目

之后

_dbContext.Clients.Add(newClient);
await _dbContext.SaveChangesAsync();

添加分离代码

_dbcontext.Entry(newClient).State = EntityState.Detached;

答案 1 :(得分:2)

您正在使用EF Core,就像编写原始SQL查询一样,这种方式优于ORM的许多优点。

您不需要ClientSecrets var newClient = new Client { ClientName = client.ClientName, ClientId = client.ClientId, ClientSecrets = secrets.ToList() // or ToArray or whatever it is }; _dbContext.Clients.Add(newClient); await _dbContext.SaveChangesAsync(); ,因为EF Core可以找出关系本身。

Client

ClientSecret需要对ClientSecret类的反向引用并不是问题,通过将您的秘密添加到模型中,您建立了ClientClient的关系。

现在保存时,EF Core会知道它首先要添加ClientSecret然后添加{{1}} s

答案 2 :(得分:0)

您好,请添加以下内容对我有用:2020年9月25日,星期五。 AsNoTracking为我解决了它。因为我能够更新我的。谢谢

var clientToUpdate = await _dbContext.AsNoTracking().Clients.Where(x => x.Id == newClientId).SingleOrDefaultAsync();

clientToUpdate.ClientSecrets.AddRange(secrets);
_dbContext.Clients.Update(clientToUpdate);
await _dbContext.SaveChangesAsync();