繁体   English   中英

在 EF Core 中添加新实体后如何更新实体

[英]How update entity after adding new entity in EF 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并从 DB 取回此对象的新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”的实例,因为已在跟踪具有相同键的此类型的另一个实例。 添加新实体时,对于大多数键类型,如果未设置键(即,如果键属性为其类型分配了默认值),将创建一个唯一的临时键值。 如果您为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。 附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文。

我该如何解决这个问题?

无法跟踪实体类型“Client”的实例,因为已在跟踪具有相同键的此类型的另一个实例

_dbContext.Clients.Add(newClient);上已经创建了一个client实例_dbContext.Clients.Add(newClient); .

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

之后

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

添加用于分离的代码

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

您正在使用 EF Core,就像您编写原始 SQL 查询时一样,这与 ORM 的许多优势相比更胜一筹。

您不需要ClientSecretsClientId ,因为 EF Core 可以自己找出关系。

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

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

现在保存时,EF Core 会知道它必须先添加Client ,然后添加ClientSecret

嗨,请添加以下内容,它适用于 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();

暂无
暂无

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

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