下面的方法将一些分离的节点作为输入参数。目标是从数据库加载任何现有的别名,将缺少的节点插入数据库,如果分离的节点的别名实体已经在数据库中,只需将其设置为数据库中的一个。
但是,在SaveChanges()上,似乎再次插入数据库中已存在的别名。我该如何解决这个问题?
internal async Task InsertMissingNodesToDb(INWatchNode[] nodes)
{
if (nodes.Any(x => x == null)) {
Trace.TraceError("Some null element in nodes array in InsertMissingNodesToDb().");
nodes = nodes.Where(x => x != null).ToArray();
}
// De-dup nodes based on ID
nodes = nodes.GroupBy(x => x.Id).Select(y => y.FirstOrDefault()).ToArray();
List<string> aliasNames = new List<string>();
foreach (var node in nodes) {
foreach (var alias in node.Aliases) {
if (!aliasNames.Contains(alias)) {
aliasNames.Add(alias);
}
}
}
using (var dbContext = Application.GetDbContext()) {
dbContext.Aliases.Where(x => aliasNames.Contains(x.Alias)).Load();
foreach (var node in nodes) {
var entityNode = await dbContext.Nodes.FindAsync(node.Id);
if (entityNode == null) {
entityNode = node is NWatchNode ? (NWatchNode)node : new NWatchNode(node);
for (int i = 0; i < entityNode.AliasEntities.Count; i++) {
var currentElement = entityNode.AliasEntities.ElementAt(i);
var loadedAlias = dbContext.Aliases.Local.
FirstOrDefault(x => x.Alias == currentElement.Alias);
if (loadedAlias != null) {
currentElement.Id = loadedAlias.Id;
currentElement = loadedAlias;
dbContext.Entry(loadedAlias).State = EntityState.Unchanged;
}
}
dbContext.Nodes.Add(entityNode);
}
}
await dbContext.SaveChangesAsync();
}
}
答案 0 :(得分:0)
我怀疑这部分代码。
entityNode.AliasEntities.ElementAt(i)
如果您希望有问题的行做某事,我认为您需要将loadedAlias
设置为currentElement
- 将loadedAlias
设置为loadedAlias
只会覆盖本地实例变量指向for (int i = 0; i < entityNode.AliasEntities.Count; i++) {
var currentElement = entityNode.AliasEntities.ElementAt(i);
var loadedAlias = dbContext.Aliases.Local.
FirstOrDefault(x => x.Alias == currentElement.Alias);
if (loadedAlias != null) {
currentElement.Id = loadedAlias.Id;
entityNode.AliasEntities.ElementAt(i) = loadedAlias;
dbContext.Entry(loadedAlias).State = EntityState.Unchanged;
}
}
并且因此看起来像无意义的代码 - 您没有通知实体其中一个预期的子项应该使用该行指向此实例。以下内容可能会阻止此问题吗?
{{1}}