Dans notre configuration assez complexe DDD
nous avons des modèles de données et des modèles de domaines. Techniquement, ils sont assez similaires avec les modèles de domaine ayant généralement des propriétés supplémentaires. Nous utilisons Automapper
pour mapper entre les objets de données et de domaine. Le problème est que dans certains cas étranges, sur SaveAsync
nous courons dans un Stackoverflow exception
. Voici le code:Automapper Stackoverflow exception avec Entity Framework
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) }
Comme vous pouvez le voir sur la ligne 16, nous effectuons un mappage vers les données de l'élément sans aucun problème. Nous avons ajouté une carte de test à la ligne 21 et les cartes sont très bien. Sur la ligne 22 est où le problème est PARFOIS. Dans la plupart des cas, cela enregistre très bien et renvoie à l'élément TDomain très bien ... mais lorsque nous essayons d'enregistrer une modification à un objet existant qui a un enfant qui référence l'objet parent, nous obtenons ce Stackoverflow exception
. J'ai fait des recherches sur cela pendant un certain temps et je peux voir 2 options qui pourraient fonctionner: 1) ajouter un MaxDepth
à la config de cette carte de sorte que cette récursivité ne va que jusqu'à présent, mais cela se sent très hacky et J'ai l'impression de masquer le problème qui pourrait devenir un cauchemar de maintenance dans le futur. L'autre option serait pour le SaveAsync
de retourner une nouvelle instance de l'objet (c'est-à-dire, la ligne 21) cela semble certainement bien mieux que le MaxDepth
mais se sent toujours un peu hacky, comme j'évite le vrai problème. En outre, toutes les valeurs dans les propriétés qui existent uniquement dans le modèle de domaine seront effacées de cette façon. Ce serait aussi un refactor assez massif qui toucherait presque 20 applications, chacune ayant 5 à 20 sauvegardes ... pas que je me plains. Peut-être que quelqu'un peut indiquer ce que je peux faire pour résoudre ce problème ou peut-être ce qui me manque ici.
Juste pour être vraiment clair, si vous supprimez la ligne 21 et de remplacer la ligne 22 avec:
mapper.Map(source: data, destination: item);
vous obtenez le même Stackoverflow exception
.