实体框架6 - 分离的实体阻止保存重复的导航属性

时间:2016-04-28 20:01:01

标签: c# entity-framework entity-framework-6

下面的方法将一些分离的节点作为输入参数。目标是从数据库加载任何现有的别名,将缺少的节点插入数据库,如果分离的节点的别名实体已经在数据库中,只需将其设置为数据库中的一个。

但是,在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();
    }
}

1 个答案:

答案 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}}