实体框架的Automapper Stackoverflow异常

时间:2017-05-12 02:15:34

标签: domain-driven-design automapper entity-framework-core one-to-one

在我们相当复杂的DDD设置中,我们有数据模型和域模型。从技术上讲,它们与通常具有附加属性的域模型非常相似。我们使用Automapper在数据和域对象之间进行映射。问题是,在某些奇怪的情况下,SaveAsync我们遇到Stackoverflow exception。这是代码:

1)    public virtual async Task SaveAsync(TDomain item)
2)    {
3)        TData data = null;
4)        if (default(TID).Equals(item.ID))
5)        {
6)            data = mapper.Map<TData>(item);
7)
8)            dataContext.Set<TData>().Add(data);
9)        }
10)       else
11)       {
12)           data = dataContext.Set<TData>().Single(x => x.ID.Equals(item.ID));
13)           if (data == null)
14)               throw new Exception($"Unable to find {typeof(TData)} with ID {item.ID} in the database.");
15)
16)           mapper.Map(source: item, destination: data);
17)       }
18)       await dataContext.SaveChangesAsync(userIdentity.ID);
19)
20)       // Update the IDs of the item and its children
21)       var domainTest = mapper.Map<TDomain>(data);
22)       mapper.Map(source: domainTest, destination: item);
23)   }

正如您在第16行所看到的,我们正在从项目映射到数据而没有任何问题。我们在第21行添加了一个测试图,并且映射得很好。第22行是问题所在的地方。在大多数情况下,这样可以保存得很好并且可以很好地映射到TDomain项目......但是当我们尝试将更改保存到具有引用父对象的子对象的现有对象时,我们得到此Stackoverflow exception。 / p>

我已经研究了很长一段时间了,我可以看到两个可行的选项:1)在这个地图的配置中添加一个MaxDepth,这样这个递归只到目前为止,但是这感觉非常hacky,感觉我正在掩盖可能在未来的某个时间成为维护噩梦的问题。另一种选择是让SaveAsync返回一个对象的新实例(即第21行),这肯定比MaxDepth方式更好,但仍然感觉有点hacky,就像我在避免真正的问题。此外,仅以域模型中存在的属性中的任何值都将以这种方式消除。这也是一个相当大规模的重构,影响了近20个应用程序,每个都有5到20个保存...不是我抱怨。也许有人可以指出我能做些什么才能真正解决这个问题,或者也许我在这里缺少什么。

要明确的是,如果删除第21行并将第22行替换为:

mapper.Map(source: data, destination: item);

你得到相同的Stackoverflow exception

1 个答案:

答案 0 :(得分:0)

现在,我已经为save方法添加了一个bool is.... = true可选参数,并且只有在此参数为true时我才会评估第22行。在那些我进入无限递归的情况下,我传递false ...我知道这真的很hacky所以我希望有人用实际的解决方案做出回应......但是这让我继续进行我的项目