c# - एंटिटी फ्रेमवर्क से एसक्लएक्सप्शन-नए लेनदेन की अनुमति नहीं है क्योंकि सत्र में अन्य धागे चल रहे हैं




entity-framework transactions (12)

मुझे वर्तमान में यह त्रुटि मिल रही है:

System.Data.SqlClient.SqlException: नए लेन-देन की अनुमति नहीं है क्योंकि सत्र में अन्य थ्रेड चल रहे हैं।

इस कोड को चलाने के दौरान:

public class ProductManager : IProductManager
{
    #region Declare Models
    private RivWorks.Model.Negotiation.RIV_Entities _dbRiv = RivWorks.Model.Stores.RivEntities(AppSettings.RivWorkEntities_connString);
    private RivWorks.Model.NegotiationAutos.RivFeedsEntities _dbFeed = RivWorks.Model.Stores.FeedEntities(AppSettings.FeedAutosEntities_connString);
    #endregion

    public IProduct GetProductById(Guid productId)
    {
        // Do a quick sync of the feeds...
        SyncFeeds();
        ...
        // get a product...
        ...
        return product;
    }

    private void SyncFeeds()
    {
        bool found = false;
        string feedSource = "AUTO";
        switch (feedSource) // companyFeedDetail.FeedSourceTable.ToUpper())
        {
            case "AUTO":
                var clientList = from a in _dbFeed.Client.Include("Auto") select a;
                foreach (RivWorks.Model.NegotiationAutos.Client client in clientList)
                {
                    var companyFeedDetailList = from a in _dbRiv.AutoNegotiationDetails where a.ClientID == client.ClientID select a;
                    foreach (RivWorks.Model.Negotiation.AutoNegotiationDetails companyFeedDetail in companyFeedDetailList)
                    {
                        if (companyFeedDetail.FeedSourceTable.ToUpper() == "AUTO")
                        {
                            var company = (from a in _dbRiv.Company.Include("Product") where a.CompanyId == companyFeedDetail.CompanyId select a).First();
                            foreach (RivWorks.Model.NegotiationAutos.Auto sourceProduct in client.Auto)
                            {
                                foreach (RivWorks.Model.Negotiation.Product targetProduct in company.Product)
                                {
                                    if (targetProduct.alternateProductID == sourceProduct.AutoID)
                                    {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found)
                                {
                                    var newProduct = new RivWorks.Model.Negotiation.Product();
                                    newProduct.alternateProductID = sourceProduct.AutoID;
                                    newProduct.isFromFeed = true;
                                    newProduct.isDeleted = false;
                                    newProduct.SKU = sourceProduct.StockNumber;
                                    company.Product.Add(newProduct);
                                }
                            }
                            _dbRiv.SaveChanges();  // ### THIS BREAKS ### //
                        }
                    }
                }
                break;
        }
    }
}

मॉडल # 1 - यह मॉडल हमारे देव सर्वर पर डेटाबेस में बैठता है। मॉडल # 1 http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/bdb2b000-6e60-4af0-a7a1-2bb6b05d8bc1/Model1.png

मॉडल # 2 - यह मॉडल हमारे प्रोड सर्वर पर डेटाबेस में बैठता है और स्वचालित फीड द्वारा प्रत्येक दिन अपडेट किया जाता है। alt text http://content.screencast.com/users/Keith.Barrows/folders/Jing/media/4260259f-bce6-43d5-9d2a-017bd9a980d4/Model2.png

नोट - मॉडल # 1 में लाल घेरे वाले आइटम वे फ़ील्ड हैं जिनका उपयोग मैं मॉडल # 2 पर "मानचित्र" करने के लिए करता हूं। कृपया मॉडल # 2 में लाल मंडलियों को अनदेखा करें: यह एक और प्रश्न से है जिसका मैंने जवाब दिया था।

नोट: मुझे अभी भी एक हटाए गए चेक में डालने की आवश्यकता है, इसलिए यदि हम अपने ग्राहक की सूची से बाहर हो गए हैं तो मैं इसे डीबी 1 से हटा सकता हूं।

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

तो बड़ा सवाल - मैं लेनदेन त्रुटि को कैसे हल कर सकता हूं? क्या मुझे लूप के माध्यम से हर बार अपना संदर्भ छोड़ने और फिर से बनाने की ज़रूरत है (मुझे समझ में नहीं आता है)?


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

उदाहरण के लिए

    using (var context = new DatabaseContext())
    {
        ...
        using (var context1 = new DatabaseContext())
        {
            ...
               context1.SaveChanges();
        }                         
        //get id of inserted object from context1 and use is.   
      context.SaveChanges();
   }

एफवाईआई: एक किताब से और कुछ लाइनों को समायोजित किया गया क्योंकि इसकी तार वैध है:

SaveChanges () विधि को आमंत्रित करना एक लेनदेन शुरू करता है जो स्वचालित रूप से डेटाबेस में बने सभी परिवर्तनों को वापस चलाता है यदि पुनरावृत्ति पूर्ण होने से पहले कोई अपवाद होता है; अन्यथा लेनदेन करता है। आप पुनरावृत्ति पूर्ण होने के बजाए प्रत्येक इकाई अद्यतन या हटाने के बाद विधि को लागू करने के लिए प्रेरित हो सकते हैं, खासकर जब आप बड़ी संख्या में संस्थाओं को अद्यतन या हटा रहे हैं।

यदि आप सभी डेटा संसाधित होने से पहले SaveChanges () को आमंत्रित करने का प्रयास करते हैं, तो आपको "नए लेनदेन की अनुमति नहीं है क्योंकि सत्र में अन्य धागे चल रहे हैं" अपवाद। अपवाद तब होता है क्योंकि SQL सर्वर किसी कनेक्शन पर एक नया लेनदेन शुरू करने की अनुमति नहीं देता है जिसमें SqlDataReader खुला होता है, कनेक्शन स्ट्रिंग द्वारा सक्षम एकाधिक सक्रिय रिकॉर्ड सेट (एमएआरएस) के साथ भी (ईएफ की डिफ़ॉल्ट कनेक्शन स्ट्रिंग एमएआरएस सक्षम करती है)

कभी-कभी यह समझने के लिए बेहतर होता है कि चीजें क्यों हो रही हैं ;-)


तो प्रोजेक्ट में मुझे यह वही समस्या थी, समस्या .toList() में नहीं थी या .toList() यह वास्तव में .toList() कॉन्फ़िगरेशन में उपयोग किया गया था। इसने कुछ अजीब स्थितियों को बनाया था, उपरोक्त त्रुटि फेंक दी गई थी, लेकिन अन्य समकक्ष त्रुटियों का एक समूह भी फेंक दिया गया था।

यह हमारा फिक्स था: इसे बदल दिया:

container.RegisterType<DataContext>().As<DbContext>().InstancePerLifetimeScope();
container.RegisterType<DbFactory>().As<IDbFactory>().SingleInstance();
container.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();

सेवा मेरे:

container.RegisterType<DataContext>().As<DbContext>().As<DbContext>();
container.RegisterType<DbFactory>().As<IDbFactory>().As<IDbFactory>().InstancePerLifetimeScope();
container.RegisterType<UnitOfWork>().As<IUnitOfWork>().As<IUnitOfWork>();//.InstancePerRequest();

नीचे दिया गया कोड मेरे लिए काम करता है:

private pricecheckEntities _context = new pricecheckEntities();

...

private void resetpcheckedtoFalse()
{
    try
    {
        foreach (var product in _context.products)
        {
            product.pchecked = false;
            _context.products.Attach(product);
            _context.Entry(product).State = EntityState.Modified;
        }
        _context.SaveChanges();
    }
    catch (Exception extofException)
    {
        MessageBox.Show(extofException.ToString());

    }
    productsDataGrid.Items.Refresh();
}

बालों से बाहर खींचने के बाद मुझे पता चला कि foreach loops अपराधी थे। ईएफ को कॉल करना क्या है, लेकिन उस लक्ष्य प्रकार के IList<T> में वापस लौटें, फिर IList<T> पर लूप करें।

उदाहरण:

IList<Client> clientList = from a in _dbFeed.Client.Include("Auto") select a;
foreach (RivWorks.Model.NegotiationAutos.Client client in clientList)
{
   var companyFeedDetailList = from a in _dbRiv.AutoNegotiationDetails where a.ClientID == client.ClientID select a;
    // ...
}

मुझे एक विशाल परिणामसेट पढ़ने और तालिका में कुछ रिकॉर्ड अपडेट करने की आवश्यकता थी। मैंने ड्रू नोएक्स के answer में सुझाए गए हिस्सों का उपयोग करने की कोशिश की।

दुर्भाग्यवश 50000 रिकॉर्ड के बाद मुझे आउटफमेमरी अपवाद मिला है। जवाब इकाई फ्रेमवर्क बड़े डेटा सेट, मेमोरी अपवाद से बाहर बताता है, कि

ईएफ डेटा की दूसरी प्रति बनाता है जो परिवर्तन पहचान के लिए उपयोग करता है (ताकि यह डेटाबेस में परिवर्तन जारी रख सके)। ईएफ संदर्भ के जीवनकाल के लिए यह दूसरा सेट रखता है और यह सेट आपको स्मृति से बाहर चला रहा है।

प्रत्येक बैच के संदर्भ को नवीनीकृत करने की सिफारिश है।

इसलिए मैंने प्राथमिक कुंजी के न्यूनतम और अधिकतम मानों को पुनर्प्राप्त कर लिया है- तालिकाओं में प्राथमिक वृद्धि कुंजी ऑटो वृद्धिशील पूर्णांक के रूप में होती है। फिर मैंने प्रत्येक खंड के संदर्भ को खोलकर रिकॉर्ड के डेटाबेस भाग से पुनर्प्राप्त किया। खंड के संदर्भ को संसाधित करने के बाद स्मृति बंद हो जाती है और रिलीज़ होती है। यह बीमा करता है कि स्मृति उपयोग बढ़ रहा है।

नीचे मेरे कोड से एक स्निपेट है:

  public void ProcessContextByChunks ()
  {
        var tableName = "MyTable";
         var startTime = DateTime.Now;
        int i = 0;
         var minMaxIds = GetMinMaxIds();
        for (int fromKeyID= minMaxIds.From; fromKeyID <= minMaxIds.To; fromKeyID = fromKeyID+_chunkSize)
        {
            try
            {
                using (var context = InitContext())
                {   
                    var chunk = GetMyTableQuery(context).Where(r => (r.KeyID >= fromKeyID) && (r.KeyID < fromKeyID+ _chunkSize));
                    try
                    {
                        foreach (var row in chunk)
                        {
                            foundCount = UpdateRowIfNeeded(++i, row);
                        }
                        context.SaveChanges();
                    }
                    catch (Exception exc)
                    {
                        LogChunkException(i, exc);
                    }
                }
            }
            catch (Exception exc)
            {
                LogChunkException(i, exc);
            }
        }
        LogSummaryLine(tableName, i, foundCount, startTime);
    }

    private FromToRange<int> GetminMaxIds()
    {
        var minMaxIds = new FromToRange<int>();
        using (var context = InitContext())
        {
            var allRows = GetMyTableQuery(context);
            minMaxIds.From = allRows.Min(n => (int?)n.KeyID ?? 0);  
            minMaxIds.To = allRows.Max(n => (int?)n.KeyID ?? 0);
        }
        return minMaxIds;
    }

    private IQueryable<MyTable> GetMyTableQuery(MyEFContext context)
    {
        return context.MyTable;
    }

    private  MyEFContext InitContext()
    {
        var context = new MyEFContext();
        context.Database.Connection.ConnectionString = _connectionString;
        //context.Database.Log = SqlLog;
        return context;
    }

FromToRange से और गुणों के साथ एक साधारण संरचना है।


मुझे भी एक ही समस्या का सामना करना पड़ रहा था।

कारण और समाधान यहां है।

http://blogs.msdn.com/b/cbiyikoglu/archive/2006/11/21/mars-transactions-and-sql-error-3997-3988-or-3983.aspx

आवेषण, अद्यतन जैसे डेटा मैनिपुलेशन कमांड को फायर करने से पहले सुनिश्चित करें कि आपने पिछले सभी सक्रिय SQL पाठकों को बंद कर दिया है।

सबसे आम त्रुटि वह कार्य है जो डीबी से डेटा पढ़ती है और मूल्यों को वापस लाती है। उदाहरण के लिए isRecordExist जैसे कार्यों।

अगर हम रिकॉर्ड प्राप्त करते हैं और पाठक को बंद करना भूल जाते हैं तो इस मामले में हम तत्काल कार्य से वापस आते हैं।


मुझे यह एक ही मुद्दा मिल रहा था लेकिन एक अलग स्थिति में। मेरे पास एक सूची बॉक्स में वस्तुओं की एक सूची थी। उपयोगकर्ता किसी आइटम पर क्लिक कर सकता है और हटाएं का चयन कर सकता है लेकिन मैं आइटम को हटाने के लिए एक संग्रहित प्रो का उपयोग कर रहा हूं क्योंकि आइटम को हटाने में बहुत सारे तर्क शामिल हैं। जब मैं संग्रहीत प्रोसेस को कॉल करता हूं तो डिलीट ठीक काम करता है लेकिन SaveChanges के लिए कोई भी भविष्य कॉल त्रुटि का कारण बनता है। मेरा समाधान ईएफ के बाहर संग्रहीत प्रो को कॉल करना था और यह ठीक काम करता था। किसी कारण से जब मैं चीजों को करने के ईएफ तरीके का उपयोग करके संग्रहित प्रो को कॉल करता हूं तो यह कुछ खुला छोड़ देता है।


मैं थोड़ा देर हो चुकी हूं, लेकिन मुझे यह त्रुटि भी मिली। मैंने यह जांच करके समस्या हल की कि कहां अपडेट किया जा रहा है।

मुझे पता चला कि मेरी क्वेरी गलत थी और वहां 250 से अधिक संपादन लंबित थे। तो मैंने अपनी क्वेरी को सही किया, और अब यह सही काम करता है।

तो मेरी स्थिति में: क्वेरी लौटने के परिणामस्वरूप डीबग करके त्रुटियों के लिए क्वेरी जांचें। उसके बाद क्वेरी सही है।

उम्मीद है कि यह भविष्य की समस्याओं को हल करने में मदद करता है।


मैं पार्टी के लिए बहुत देर हो चुकी हूं लेकिन आज मुझे एक ही त्रुटि का सामना करना पड़ा और मैंने कैसे हल किया सरल था। मेरा परिदृश्य इस दिए गए कोड के समान था, मैं प्रत्येक लूप के लिए नेस्टेड के अंदर डीबी लेनदेन कर रहा था।

समस्या यह है कि सिंगल डीबी लेनदेन के लिए प्रत्येक लूप के मुकाबले थोड़ा सा समय लगता है, इसलिए एक बार जब पहले लेनदेन पूरा नहीं हो जाता है तो नया कर्षण एक अपवाद फेंकता है, इसलिए समाधान प्रत्येक लूप के लिए एक नई वस्तु बनाना है जहां आप एक डीबी लेनदेन कर रहे हैं।

उपर्युक्त परिदृश्यों के लिए समाधान इस तरह होगा:

foreach (RivWorks.Model.Negotiation.AutoNegotiationDetails companyFeedDetail in companyFeedDetailList)
                {
private RivWorks.Model.Negotiation.RIV_Entities _dbRiv = RivWorks.Model.Stores.RivEntities(AppSettings.RivWorkEntities_connString);
                    if (companyFeedDetail.FeedSourceTable.ToUpper() == "AUTO")
                    {
                        var company = (from a in _dbRiv.Company.Include("Product") where a.CompanyId == companyFeedDetail.CompanyId select a).First();
                        foreach (RivWorks.Model.NegotiationAutos.Auto sourceProduct in client.Auto)
                        {
                            foreach (RivWorks.Model.Negotiation.Product targetProduct in company.Product)
                            {
                                if (targetProduct.alternateProductID == sourceProduct.AutoID)
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                var newProduct = new RivWorks.Model.Negotiation.Product();
                                newProduct.alternateProductID = sourceProduct.AutoID;
                                newProduct.isFromFeed = true;
                                newProduct.isDeleted = false;
                                newProduct.SKU = sourceProduct.StockNumber;
                                company.Product.Add(newProduct);
                            }
                        }
                        _dbRiv.SaveChanges();  // ### THIS BREAKS ### //
                    }
                }

सूची के रूप में हमेशा अपने चयन का प्रयोग करें

उदाहरण के लिए:

var tempGroupOfFiles = Entities.Submited_Files.Where(r => r.FileStatusID == 10 && r.EventID == EventId).ToList();

फिर परिवर्तनों को सहेजते समय संग्रह के माध्यम से लूप करें

 foreach (var item in tempGroupOfFiles)
             {
                 var itemToUpdate = item;
                 if (itemToUpdate != null)
                 {
                     itemToUpdate.FileStatusID = 8;
                     itemToUpdate.LastModifiedDate = DateTime.Now;
                 }
                 Entities.SaveChanges();

             }

हमने अब कनेक्ट पर खोले गए बग पर आधिकारिक प्रतिक्रिया पोस्ट की है। हम जिन कामकाजों की सिफारिश करते हैं वे निम्नानुसार हैं:

यह त्रुटि SaveChanges () कॉल के दौरान एक अंतर्निहित लेनदेन बनाने वाली इकाई फ्रेमवर्क के कारण है। त्रुटि के आसपास काम करने का सबसे अच्छा तरीका एक अलग पैटर्न का उपयोग करना है (यानी, पढ़ने के बीच में बचत नहीं करना) या स्पष्ट रूप से लेनदेन घोषित करना। यहां तीन संभावित समाधान दिए गए हैं:

// 1: Save after iteration (recommended approach in most cases)
using (var context = new MyContext())
{
    foreach (var person in context.People)
    {
        // Change to person
    }
    context.SaveChanges();
}

// 2: Declare an explicit transaction
using (var transaction = new TransactionScope())
{
    using (var context = new MyContext())
    {
        foreach (var person in context.People)
        {
            // Change to person
            context.SaveChanges();
        }
    }
    transaction.Complete();
}

// 3: Read rows ahead (Dangerous!)
using (var context = new MyContext())
{
    var people = context.People.ToList(); // Note that this forces the database
                                          // to evaluate the query immediately
                                          // and could be very bad for large tables.

    foreach (var person in people)
    {
        // Change to person
        context.SaveChanges();
    }
} 






transactions