अपडेट करें: ऑटोमैपर इसे साधारण मामलों में स्वचालित रूप से लागू करता है क्योंकि यह पहले से ही एक ToList()< /ए>. जिस मुद्दे को मैं देख रहा हूं जिसके कारण मुझे यह प्रश्न खोलने के लिए प्रेरित किया गया, वह एक अधिक जटिल मुद्दा बन गया (SoftwareIds सदस्य N+1 का अपराधी है। देखें यह।)


EF Core 2.1 में, हमने परिणामों को बफ़र करने और N+1 डेटाबेस क्वेरी से बचने के लिए LINQ सबक्वेरी पर ToList() जोड़ने के लिए समर्थन प्राप्त किया। (दस्तावेज़) यह एक DbContext के विरुद्ध सादे LINQ प्रश्नों पर बहुत अच्छा काम करता है।

हालांकि, अगर मेरे पास ऑटोमैपर प्रोफ़ाइल है जिसके परिणामस्वरूप एन + 1 प्रश्न हैं:

    public MyMappingProfile() =>
        CreateMap<MyEntity, MyDto>().ForMember(e => e.MyCollectionProp, o => o.MapFrom(l => l.MyCollectionPropMany.Select(la => la.MyCollectionEntity)))

ToList() जोड़ना एक अपवाद फेंकता है:

    public MyMappingProfile() =>
        CreateMap<MyEntity, MyDto>().ForMember(e => e.MyCollectionProp, o => o.MapFrom(l => l.MyCollectionPropMany.Select(la => la.MyCollectionEntity).ToList()))

System.NotSupportedException: 'अभिव्यक्ति को पार्स नहीं कर सका' MyDto.MyCollectionPropMany.Select(la => la.MyCollectionEntity).ToList ()': 'System.Linq.Enumerable.ToList' विधि का यह अधिभार वर्तमान में समर्थित नहीं है।'

क्या ऑटोमैपर प्रोफ़ाइल में सबक्वेरी बफरिंग को सक्षम करने का कोई तरीका है?

मॉडल:

public class MyEntity
{
    public int Id { get; set; }
    public ICollection<MyCollectionPropMany> MyCollectionPropManys { get; set; }
    ...
}

public class MyCollectionPropMany
{
    public int MyEntityId { get; set; }
    public MyEntity MyEntity { get; set; }
    public int MyCollectionPropId { get; set; }
    public MyCollectionProp MyCollectionProp { get; set; }
}

public class MyCollectionProp
{
    public int Id { get; set; }
    public ICollection<MyCollectionPropMany> MyCollectionPropManys { get; set; }
    ...
}

public class MyDto
{
    public int Id { get; set; }
    public IEnumerable<MyCollectionPropDto> MyCollectionPropDtos { get; set; }
    ...
}

public class MyCollectionPropDto
{
    public string Name { get; set; }
    ...
}

ऑटोमैपर v7.0.1

वास्तविक परिदृश्य (मैंने SO के लिए सामान्य/सरल बनाने की कोशिश की): स्रोत इस वास्तविक उदाहरण में, Languages और Tags सदस्य अनेक-से-अनेक के माध्यम से वर्तमान में N+1 क्वेरी जेनरेट कर रहे हैं।

2
Collin Barrett 17 सितंबर 2018, 16:10

1 उत्तर

सबसे बढ़िया उत्तर

यह पता चला है कि ऑटोमैपर कभी-कभी स्वचालित रूप से ToList / ToArray को प्रोजेक्शन एक्सप्रेशन में जोड़ देता है जब गणना योग्य प्रकारों को मैप किया जाता है, कभी-कभी नहीं।

नियम इस प्रकार प्रतीत होता है। यदि गंतव्य गणना योग्य प्रकार स्रोत अभिव्यक्ति प्रकार से सीधे असाइन करने योग्य है, तो AutoMapper सीधे स्रोत अभिव्यक्ति का उपयोग करता है। दूसरे शब्दों में, यदि निम्नलिखित असाइनमेंट मान्य है (छद्म कोड):

dst.Member = src.Expression;

इस मामले में, यह आप पर निर्भर है कि आप अपने मैपिंग एक्सप्रेशन में ToList को शामिल करें या नहीं (इस प्रकार EF Core सहसंबद्ध क्वेरी ऑप्टिमाइज़ेशन के लिए ऑप्ट-इन करें)।

अन्य सभी मामलों में AutoMapper यदि आवश्यक हो तो गणना करने योग्य तत्व मैपिंग करता है और फिर ToArray या ToList जोड़ता है। ऑप्ट-आउट करने का कोई तरीका नहीं है।

शीघ्र ही, यदि गंतव्य गणना योग्य तत्व प्रकार यदि Dto (मैपिंग की आवश्यकता है), नहीं स्रोत LINQ अभिव्यक्ति में ToList शामिल करें, यदि यह आदिम या इकाई प्रकार है, तो करें em> N + 1 प्रश्नों से बचने के लिए ToList शामिल करें। यह सब तब लागू होता है जब गंतव्य संग्रह प्रकार IEnumerable<T> हो। कोई अन्य व्युत्पन्न संग्रह प्रकार जैसे IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>, List<T>, T[] आदि ऑटोमैपर द्वारा स्वचालित रूप से संभाला जाएगा यदि स्रोत व्यंजक IEnumerable<TSource> लौटाता है।

2
Ivan Stoev 20 सितंबर 2018, 10:25