खोज…


AsNoTracking का उपयोग करना

खराब उदाहरण:

var location =  dbContext.Location
                     .Where(l => l.Location.ID == location_ID)
                     .SingleOrDefault();

return location;

चूँकि उपरोक्त कोड किसी इकाई को संशोधित या जोड़े बिना वापस कर रहा है, इसलिए हम ट्रैकिंग लागत से बच सकते हैं।

अच्छा उदाहरण:

var location =  dbContext.Location.AsNoTracking()
                     .Where(l => l.Location.ID == location_ID)
                     .SingleOrDefault();

return location;

जब हम फ़ंक्शन AsNoTracking() उपयोग करते हैं, तो हम स्पष्ट रूप से Entity फ्रेमवर्क को बता रहे हैं कि संस्थाओं को संदर्भ द्वारा ट्रैक नहीं किया गया है। आपके डेटा स्टोर से बड़ी मात्रा में डेटा प्राप्त करते समय यह विशेष रूप से उपयोगी हो सकता है। यदि आप अन-ट्रैक किए गए संस्थाओं में परिवर्तन करना चाहते हैं, तो आपको SaveChanges कॉल करने से पहले उन्हें संलग्न करना याद रखना चाहिए।

केवल आवश्यक डेटा लोड हो रहा है

कोड में अक्सर देखी जाने वाली एक समस्या सारा डेटा लोड कर रही है। यह सर्वर पर लोड को बहुत बढ़ा देगा।

मान लें कि मेरे पास "स्थान" नामक एक मॉडल है जिसमें 10 फ़ील्ड हैं, लेकिन सभी फ़ील्ड एक ही समय में आवश्यक नहीं हैं। मान लें कि मैं केवल उस मॉडल का 'स्थान नाम' पैरामीटर चाहता हूं।

खराब उदाहरण

var location =  dbContext.Location.AsNoTracking()
                         .Where(l => l.Location.ID == location_ID)
                         .SingleOrDefault();

return location.Name;

अच्छा उदाहरण

var location =  dbContext.Location
                          .Where(l => l.Location.ID == location_ID)
                          .Select(l => l.LocationName);
                          .SingleOrDefault();

return location;

"अच्छे उदाहरण" में कोड केवल 'LocationName' प्राप्त करेगा और कुछ नहीं।

ध्यान दें कि चूंकि इस उदाहरण में कोई इकाई नहीं दी गई है, AsNoTracking() आवश्यक नहीं है। वैसे भी नज़र रखने के लिए कुछ भी नहीं है।

बेनामी प्रकार के साथ अधिक फ़ील्ड प्राप्त करना

var location = dbContext.Location
                    .Where(l => l.Location.ID == location_ID)
                    .Select(l => new { Name = l.LocationName, Area = l.LocationArea })
                    .SingleOrDefault();

return location.Name + " has an area of " + location.Area;

पहले के उदाहरण के रूप में, केवल 'लोकेशननाम' और 'लोकेशन' नाम के फ़ील्ड को डेटाबेस से पुनर्प्राप्त किया जाएगा, बेनामी प्रकार आपके इच्छित कई मान रख सकता है।

जब संभव हो तो डेटाबेस में प्रश्नों का निष्पादन करें, स्मृति में नहीं।

मान लीजिए कि हम टेक्सास में कितने काउंटियों की गिनती करना चाहते हैं:

var counties = dbContext.States.Single(s => s.Code == "tx").Counties.Count();

क्वेरी सही है, लेकिन अक्षम है। States.Single(…) डेटाबेस से एक स्थिति लोड करता है। इसके बाद, Counties ने एक दूसरे क्वेरी में अपने सभी क्षेत्रों के साथ सभी 254 काउंटियों को लोड किया। .Count() तो लोडेड Counties संग्रह पर स्मृति में किया जाता है
हमने बहुत सारे डेटा लोड किए हैं जिनकी हमें आवश्यकता नहीं है, और हम बेहतर कर सकते हैं:

var counties = dbContext.Counties.Count(c => c.State.Code == "tx");

यहां हम केवल एक क्वेरी करते हैं, जो SQL में काउंट और जॉइन में बदल जाती है। हम डेटाबेस से केवल गिनती लौटाते हैं - हमने पंक्तियों, फ़ील्ड्स, और ऑब्जेक्ट्स के निर्माण को सहेजा है।

यह देखना आसान है कि संग्रह प्रकार को देखते हुए क्वेरी कहां बनाई गई है: IQueryable<T> बनाम IEnumerable<T>

कई प्रश्नों को async और समानांतर में निष्पादित करें

Async क्वेरीज़ का उपयोग करते समय, आप एक ही समय में कई क्वेरीज़ निष्पादित कर सकते हैं, लेकिन एक ही संदर्भ में नहीं। यदि एक क्वेरी का निष्पादन समय 10s है, तो खराब उदाहरण के लिए समय 20s होगा, जबकि अच्छे उदाहरण के लिए समय 10s होगा।

खराब उदाहरण

IEnumerable<TResult1> result1;
IEnumerable<TResult2> result2;

using(var context = new Context())
{
    result1 = await context.Set<TResult1>().ToListAsync().ConfigureAwait(false);
    result2 = await context.Set<TResult1>().ToListAsync().ConfigureAwait(false);
}

अच्छा उदाहरण

public async Task<IEnumerable<TResult>> GetResult<TResult>()
{
    using(var context = new Context())
    {
        return await context.Set<TResult1>().ToListAsync().ConfigureAwait(false);
    }
}



IEnumerable<TResult1> result1;
IEnumerable<TResult2> result2;

var result1Task = GetResult<TResult1>();
var result2Task = GetResult<TResult2>();

await Task.WhenAll(result1Task, result2Task).ConfigureAwait(false);

var result1 = result1Task.Result;
var result2 = result2Task.Result;

ट्रैकिंग और प्रॉक्सी पीढ़ी को अक्षम करें

यदि आप केवल डेटा प्राप्त करना चाहते हैं, लेकिन कुछ भी संशोधित नहीं करते हैं, तो आप परिवर्तन ट्रैकिंग और प्रॉक्सी निर्माण को बंद कर सकते हैं। यह आपके प्रदर्शन को बेहतर करेगा और आलसी लोडिंग को भी रोकेगा।

खराब उदाहरण:

using(var context = new Context())
{
    return await context.Set<MyEntity>().ToListAsync().ConfigureAwait(false);
}

अच्छा उदाहरण:

using(var context = new Context())
{
    context.Configuration.AutoDetectChangesEnabled = false;
    context.Configuration.ProxyCreationEnabled = false;

    return await context.Set<MyEntity>().ToListAsync().ConfigureAwait(false);
}

अपने संदर्भ के निर्माता के भीतर से इन्हें बंद करना विशेष रूप से सामान्य है, खासकर यदि आप चाहें तो इन्हें आपके समाधान के दौरान सेट किया जा सकता है:

public class MyContext : DbContext
{
    public MyContext()
        : base("MyContext")
    {
        Configuration.AutoDetectChangesEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }

    //snip
}

जिद्दी संस्थाओं के साथ काम करना

कहते हैं कि हमारे पास कई-से-कई संबंधों में Product और Category :

public class Product
{
    public Product()
    {
        Categories = new HashSet<Category>();
    }
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public virtual ICollection<Category> Categories { get; private set; }
}

public class Category
{
    public Category()
    {
        Products = new HashSet<Product>();
    }
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

हम एक जोड़ना चाहते हैं Category एक के लिए Product , हम उत्पाद लोड और उसके लिए श्रेणी जोड़ने के लिए Categories , उदाहरण के लिए:

खराब उदाहरण:

var product = db.Products.Find(1);
var category = db.Categories.Find(2);
product.Categories.Add(category);
db.SaveChanges();

(जहाँ db एक DbContext उपवर्ग है)।

यह Product और Category बीच जंक्शन तालिका में एक रिकॉर्ड बनाता है। हालाँकि, इस तालिका में केवल दो Id मान हैं। एक छोटे से रिकॉर्ड को बनाने के लिए दो पूर्ण संस्थाओं को लोड करना संसाधनों की बर्बादी है।

एक अधिक कुशल तरीका स्टब एंटिटीज़ यानी इकाई ऑब्जेक्ट्स का उपयोग करना है, जो मेमोरी में बनाए जाते हैं, जिसमें केवल नंगे न्यूनतम डेटा होते हैं, आमतौर पर केवल एक Id वैल्यू। यह है जो ऐसा लग रहा है:

अच्छा उदाहरण:

// Create two stub entities
var product = new Product { ProductId = 1 };
var category = new Category { CategoryId = 2 };

// Attach the stub entities to the context
db.Entry(product).State = System.Data.Entity.EntityState.Unchanged;
db.Entry(category).State = System.Data.Entity.EntityState.Unchanged;

product.Categories.Add(category);
db.SaveChanges();

अंतिम परिणाम समान है, लेकिन यह डेटाबेस के लिए दो राउंडट्रिप्स से बचा जाता है।

डुप्लिकेट को रोकें

यह जांचना चाहते हैं कि क्या एसोसिएशन पहले से मौजूद है, एक सस्ता क्वेरी पर्याप्त है। उदाहरण के लिए:

var exists = db.Categories.Any(c => c.Id == 1 && c.Products.Any(p => p.Id == 14));

फिर, यह पूर्ण संस्थाओं को मेमोरी में लोड नहीं करेगा। यह प्रभावी रूप से जंक्शन तालिका पर सवाल उठाता है और केवल एक बूलियन देता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow