Client
とClientSecret
の2つのテーブルがあります。テーブルの構造は次のとおりです。
_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
を作成してClientId
とClientName
を設定し、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'のインスタンスは、同じキーを持つこのタイプの別のインスタンスがすでに追跡されているため、追跡できません。新しいエンティティを追加するとき、ほとんどのキータイプでは、キーが設定されていない場合(つまり、キープロパティにそのタイプのデフォルト値が割り当てられている場合)、一意の一時キー値が作成されます。新しいエンティティのキー値を明示的に設定する場合は、それらが既存のエンティティまたは他の新しいエンティティ用に生成された一時的な値と衝突しないようにしてください。既存のエンティティをアタッチするときは、特定のキー値を持つ1つのエンティティインスタンスのみがコンテキストにアタッチされていることを確認してください。
この問題を修正するにはどうすればよいですか?
同じキーを持つこのタイプの別のインスタンスがすでに追跡されているため、エンティティタイプ「クライアント」のインスタンスを追跡できません
_dbContext.Clients.Add(newClient);
で作成されたclient
のインスタンスがすでに存在します。
更新されたエントリを添付する前に、最初のエントリを切り離す必要があります
後
_dbContext.Clients.Add(newClient);
await _dbContext.SaveChangesAsync();
切り離すためのコードを追加する
_dbcontext.Entry(newClient).State = EntityState.Detached;
生のSQLクエリを作成するときと同じようにEFCoreを使用しています。これは、ORMの多くの利点を上回っています。
EF Coreは関係自体を把握できるため、ClientId
に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();
ClientSecretがClient
クラスへの逆参照を必要とすることは問題ではありません。モデルにシークレットを追加することで、ClientSecret
とClient
の関係を確立します。
ここで保存すると、EF Coreは、最初にClient
を追加してから、ClientSecret
sを追加する必要があることを認識します。