एंटिटी फ्रेमवर्क कोर: पिछले ऑपरेशन पूरा होने से पहले इस संदर्भ में एक दूसरा ऑपरेशन शुरू हुआ


98

मैं Entity फ्रेमवर्क कोर का उपयोग करके ASP.Net Core 2.0 परियोजना पर काम कर रहा हूं

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0"/>

और मेरी सूची विधियों में से एक में मुझे यह त्रुटि मिल रही है:

InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()

यह मेरी विधि है:

    [HttpGet("{currentPage}/{pageSize}/")]
    [HttpGet("{currentPage}/{pageSize}/{search}")]
    public ListResponseVM<ClientVM> GetClients([FromRoute] int currentPage, int pageSize, string search)
    {
        var resp = new ListResponseVM<ClientVM>();
        var items = _context.Clients
            .Include(i => i.Contacts)
            .Include(i => i.Addresses)
            .Include("ClientObjectives.Objective")
            .Include(i => i.Urls)
            .Include(i => i.Users)
            .Where(p => string.IsNullOrEmpty(search) || p.CompanyName.Contains(search))
            .OrderBy(p => p.CompanyName)
            .ToPagedList(pageSize, currentPage);

        resp.NumberOfPages = items.TotalPage;

        foreach (var item in items)
        {
            var client = _mapper.Map<ClientVM>(item);

            client.Addresses = new List<AddressVM>();
            foreach (var addr in item.Addresses)
            {
                var address = _mapper.Map<AddressVM>(addr);
                address.CountryCode = addr.CountryId;
                client.Addresses.Add(address);
            }

            client.Contacts = item.Contacts.Select(p => _mapper.Map<ContactVM>(p)).ToList();
            client.Urls = item.Urls.Select(p => _mapper.Map<ClientUrlVM>(p)).ToList();
            client.Objectives = item.Objectives.Select(p => _mapper.Map<ObjectiveVM>(p)).ToList();
            resp.Items.Add(client);
        }

        return resp;
    }

मैं विशेष रूप से थोड़ा खो गया हूं क्योंकि यह काम करता है जब मैं इसे स्थानीय रूप से चलाता हूं, लेकिन जब मैं अपने स्टेजिंग सर्वर (IIS 8.5) पर तैनात होता हूं तो मुझे यह त्रुटि मिलती है और यह सामान्य रूप से काम कर रहा था। मेरे एक मॉडल की अधिकतम लंबाई बढ़ाने के बाद त्रुटि दिखाई देने लगी। मैंने संबंधित व्यू मॉडल की अधिकतम लंबाई भी अपडेट की है। और कई अन्य सूची विधियां हैं जो बहुत समान हैं और वे काम कर रही हैं।

मेरे पास एक Hangfire काम चल रहा था, लेकिन यह नौकरी एक ही इकाई का उपयोग नहीं करती है। यही सब मैं प्रासंगिक होने के लिए सोच सकता हूं। इसका क्या कारण हो सकता है?


1
इसकी जाँच करें
बर्काय

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

एक पूर्ण स्टैक ट्रेस देखना अच्छा होगा
Evk

और यह जानने के लिए कि क्या एकाधिक सक्रिय परिणाम सक्षम हैं
Jay

एक ही समस्या होने के बाद मुझे पता चला कि मैंने अपने डेटाबेस तालिका में अशक्त पूर्णांकों को रखा था। जैसे ही मैंने अपनी इकाई के मॉडल गुणों को अशक्त इंटेंस से मिलान करने के लिए सेट किया, यह सब काम करना शुरू कर दिया, संदेश मेरे लिए भ्रामक थे ...!
AlwaysLearning

जवाबों:


98

मुझे यकीन नहीं है कि यदि आप अपने DbContext को हल करने के लिए IoC और डिपेंडेंसी इंजेक्शन का उपयोग कर रहे हैं, तो कभी भी इसका उपयोग किया जा सकता है। यदि आप करते हैं और आप नेट कोर (या किसी अन्य IoC- कंटेनर) से देशी IoC का उपयोग कर रहे हैं और आपको यह त्रुटि मिल रही है, तो अपने DbContext को Transient के रूप में पंजीकृत करना सुनिश्चित करें। कर

services.AddTransient<MyContext>();

या

services.AddDbContext<MyContext>(ServiceLifetime.Transient);

के बजाय

services.AddDbContext<MyContext>();

AddDbContext ने संदर्भ को स्कोप के रूप में जोड़ा है, जो कई थ्रेड्स के साथ काम करते समय परेशानी का कारण हो सकता है।

इसके अलावा, async / प्रतीक्षारत परिचालन इस व्यवहार का कारण बन सकता है, जब async lambda अभिव्यक्तियों का उपयोग किया जाता है।

क्षणिक के रूप में इसे जोड़ने से इसके डाउनसाइड भी होते हैं। आप कई वर्गों पर कुछ इकाई में परिवर्तन नहीं कर पाएंगे जो संदर्भ का उपयोग कर रहे हैं क्योंकि प्रत्येक वर्ग को आपके DbContext का अपना उदाहरण मिलेगा।

इसके लिए सरल व्याख्या यह है कि DbContextकार्यान्वयन थ्रेड-सुरक्षित नहीं है। आप इसके बारे में और अधिक यहाँ पढ़ सकते हैं


2
जब मैं क्षणिक का उपयोग करता हूं तो मुझे निम्नलिखित त्रुटि मिलती है (बंद या निपटारा) 'OmniService.DataAccess.Models.OmniServiceDbContext'। System.ObjectDisposedException: किसी डिस्पोज़्ड ऑब्जेक्ट को एक्सेस नहीं कर सकता। इस त्रुटि का एक सामान्य कारण एक संदर्भ को निपटाना है जो निर्भरता इंजेक्शन से हल किया गया था और फिर बाद में उसी संदर्भ उदाहरण का उपयोग आपके आवेदन में कहीं और करने की कोशिश कर रहा है। यह तब हो सकता है यदि आप संदर्भ में डिस्पोज़ () का उपयोग कर रहे हैं, या एक उपयोग कथन में संदर्भ को लपेट रहे हैं। ... ऑब्जेक्ट नाम: 'AsyncDisposer'।
डेविड

5
हाय डेविड! मुझे लगता है कि आप Task.Run(async () => context.Set...)इसे प्रतीक्षा किए बिना उपयोग कर रहे हैं या परिणाम की प्रतीक्षा किए बिना एक scoped db संदर्भ बना रहे हैं। इसका मतलब यह है कि आपके संदर्भ को संभवतः पहले से ही इसका उपयोग करते समय निपटाया जाता है। यदि आप Microsoft DI पर हैं, तो आपको अपने भीतर एक निर्भरता गुंजाइश बनानी होगी Task.Run। इन लिंक को भी देखें। stackoverflow.com/questions/45047877/… डॉक्स .microsoft.com
us/

3
जैसा कि पहले बताया गया है, यदि आप प्रतीक्षारत कीवर्ड के साथ एक async विधि को कॉल करने से चूक जाते हैं, तो आप इस समस्या का सामना करेंगे।
यनफर

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

3
@ सालमी तुम मेरे हीरो हो। दर्दनाक डिबगिंग के 6 घंटे। यह उपाय था। यदि कोई व्यक्ति IHttpContextAccessor को DbContext में इंजेक्ट कर रहा है और दावे शून्य हैं, तो यह समाधान है। बहुत बहुत शुक्रिया यार।
jcmontx

62

कुछ मामलों में, यह त्रुटि तब होती है जब कीवर्ड के बिना एक एसिंक्स विधि को कॉल किया जाता है await, जिसे केवल awaitविधि कॉल से पहले जोड़कर हल किया जा सकता है । हालाँकि, उत्तर उल्लेखित प्रश्न से संबंधित नहीं हो सकता है लेकिन यह एक समान त्रुटि को हल करने में मदद कर सकता है।


5
मेरे साथ ऐसा हुआ। काम First()करने के लिए बदल रहा है await / FirstAsync()
गुइलहर्मे

वोट दें। यह भी देखें jimlynn.wordpress.com/2017/11/16/… जिम लिन " एन्ट्री फ्रेंडवर्कर त्रुटि: इस संपर्क में आने से पहले बचना आवश्यक है । किसी भी संस्मरणकर्ता को सुरक्षित रखने के लिए कोई गारंटी नहीं है"।
ग्रेनडाकोडर

इसके लिए धन्यवाद! यह वास्तव में मेरी समस्या थी ... एक async mdethod पर एक प्रतीक्षा जोड़ना भूल गया।
एक्सलवैक

मेरे साथ भी हुआ, और इस टिप्पणी ने मदद की जैसे मैंने खोजा है कि मैं एक लापता प्रतीक्षा कहाँ भूल गया था। एक बार जब मैंने इसे पाया, तो समस्या हल हो गई।
सिय्योन हाई

इसके लिए मेरे लिए काम किया, बहुत बहुत धन्यवाद
zoha_sh

43

अपवाद का मतलब है कि _contextएक ही समय में दो धागे द्वारा उपयोग किया जा रहा है; या तो एक ही अनुरोध में दो धागे, या दो अनुरोधों द्वारा।

क्या आपका _contextघोषित स्टेटिक शायद हो सकता है? यह नहीं होना चाहिए।

या आप GetClientsअपने कोड में कहीं और से एक ही अनुरोध में कई बार कॉल कर रहे हैं ?

आप पहले से ही ऐसा कर रहे होंगे, लेकिन आदर्श रूप से, आप अपने लिए निर्भरता इंजेक्शन का उपयोग DbContextकर रहे होंगे, जिसका अर्थ है कि आप AddDbContext()अपने स्टार्टअप में उपयोग कर रहे हैं। और आपका नियंत्रक निर्माता कुछ इस तरह दिखाई देगा:

private readonly MyDbContext _context; //not static

public MyController(MyDbContext context) {
    _context = context;
}

यदि आपका कोड ऐसा नहीं है, तो हमें दिखाएं और हो सकता है कि हम आगे मदद कर सकें।


1
शायद यह मेरे पास काम है। मैं हल करने में कामयाब रहा, मेरा जवाब देखें। लेकिन मैं तुम्हें सही एक के रूप में चिह्नित कर रहा हूं
एंड्रे लुइज़

मेरा कोड बिल्कुल इस तरह है और हम अक्सर ट्रैक करते हैं "पिछले असिंक्रोनस ऑपरेशन पूरा होने से पहले इस संदर्भ में एक दूसरा ऑपरेशन शुरू हुआ। इस संदर्भ में किसी अन्य विधि को कॉल करने से पहले यह सुनिश्चित करने के लिए कि किसी भी एसिंक्रोनस संचालन ने पूरा किया है। थ्रेड सुरक्षित होने की गारंटी। - System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered () "पर।
एनएमथुर

@NMathur क्या आप _contextअन्य थ्रेड्स में अपनी वस्तु का उपयोग कर रहे हैं ? Task.Run()उदाहरण के लिए अंदर की तरह ?
गेब्रियल लुसी

@GabrielLuci मेरे सभी तरीके नीचे की तरह ही हैं, क्या यह समस्या का कारण होगा। इस विषय के बारे में मेरा ज्ञान बहुत कम है। क्या आप सुझाव दे सकते हैं कि इन व्यवहारों को समझने के लिए मुझे कहाँ और क्या पढ़ना चाहिए? सार्वजनिक async टास्क <सूची <आइटम >> GetItems (int orderId) {सूची <आइटम> आइटम = प्रतीक्षा _context.Item। कहां (x => x.OrderId == orderId) .ToLitAsync (); सामान वापस करे; }
एनएमथुर

@NMathur यह ठीक लग रहा है। बस सुनिश्चित करें कि आप हमेशा awaitasync विधियों का उपयोग कर रहे हैं । यदि आप उपयोग नहीं करते हैं await, तो आप अनजाने में मल्टी-थ्रेडिंग कर सकते हैं।
गेब्रियल लुसी

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

           services.AddDbContext<Context>(options =>
                            options.UseSqlServer(_configuration.GetConnectionString("ContextConn")),
                 ServiceLifetime.Transient);
    

यह विधि उन मामलों में समस्या पैदा करेगी जहां बहु-उपयोगकर्ता तत्काल लेनदेन की संख्या अधिक है।
हक्कंतोपुज

11

मुझे भी यही समस्या थी और यह पता चला कि मूल सेवा एक सिंगलटन थी। तो संदर्भ स्वतः ही सिंगलटन भी बन गया। भले ही डि में लाइफटाइम स्कॉप्ड के रूप में घोषित किया गया था।

दूसरे में विभिन्न जन्मों के साथ इंजेक्शन लगाने की सेवा

  1. कभी भी स्कोप्ड और क्षणिक सेवाओं को सिंगलटन सेवा में न डालें। (यह प्रभावी रूप से एकल में क्षणिक या स्कोप्ड सेवा को परिवर्तित करता है।)

  2. कभी भी क्षणिक सेवाओं में क्षणिक सेवाओं को इंजेक्ट न करें (यह क्षणिक सेवा को scoped में परिवर्तित करता है।)


यह मेरा मुद्दा था
जोन्सोपोलिस

मेरी भी यही समस्या थी। मैं एक हैंडलर वर्ग को सिंगलटन के रूप में और DbContext को क्षणिक के रूप में पंजीकृत कर रहा था। मुझे हैंडलर क्लास के भीतर ServiceProvider का उपयोग करना पड़ा, DI कंटेनर से हर समय एक आसान उदाहरण प्राप्त करने के लिए हैंडलर को फिट किया जाता है
Daiana Sodré

6

मुझे लगता है कि यह उत्तर अभी भी कुछ को मदद कर सकता है और कई बार बचा सकता है। मैं बदल कर एक समान समस्या हल हो जाती IQueryableलिए List(या सरणी, संग्रह ... के लिए)।

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

var list=_context.table1.where(...);

सेवा

var list=_context.table1.where(...).ToList(); //or ToArray()...

3
IMHO, यह उत्तर माइनस पॉइंट के लायक नहीं है, यह सिर्फ खराब तरीके से व्यक्त किया गया है। .ToList () वास्तव में अधिकांश समस्याओं को हल करता है "एक दूसरा ऑपरेशन ..." इस तथ्य के कारण कि यह अभिव्यक्ति के तत्काल मूल्यांकन को मजबूर करता है। इस तरह से कोई कतार संदर्भ प्रसंग नहीं हैं।
वासिलाग

1
मेरे मामले में यह मुद्दा था। मेरे पास एक क्वेरी के क्लॉज़ में xxx.Contains (z.prop) था। xxx को पहले वाले क्वेरी से हल किया गया एक अलग int [] सरणी माना जाता था। दुर्भाग्य से, जब तक दूसरी क्वेरी हिट नहीं हुई, तब तक xxx अभी भी एक IQueryable था। दूसरे प्रश्न से पहले xxx.ToArray () जोड़ना मेरे मुद्दे को तय करता है।
जेसन बोउता

5

मेरी भी यही त्रुटि थी। ऐसा इसलिए हुआ क्योंकि मैंने एक ऐसी विधि को बुलाया था जिसका निर्माण public async void ...इसके बजाय किया गया था public async Task ...


2

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

Task task = Task.Run(() =>
    {
        using (var scope = serviceScopeFactory.CreateScope())
        {
            var otherOfferService = scope.ServiceProvider.GetService<IOfferService>();
            // everything was ok here. then I did: 
            productService.DoSomething(); // (from the main scope) and this failed because the db context associated to that service was already disposed.
            ...
        }
    }

मुझे यह करना चाहिए:

var otherProductService = scope.ServiceProvider.GetService<IProductService>();
otherProductService.DoSomething();

क्या संदर्भ केवल तभी सामने नहीं आएगा जब उपयोग करने वाले ब्लॉक में सब कुछ निष्पादन पूर्ण हो गया हो?
सेलो म्कांतजवा

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

2

मेरी स्थिति अलग है: मैं 30 उपयोगकर्ताओं के साथ डेटाबेस को विशिष्ट भूमिकाओं से संबंधित करने की कोशिश कर रहा था, इसलिए मैं यह कोड चला रहा था:

for (var i = 1; i <= 30; i++)
{
    CreateUserWithRole("Analyst", $"analyst{i}", UserManager);
}

यह एक सिंक फंक्शन था। इसके अंदर मेरे पास 3 कॉल थे:

UserManager.FindByNameAsync(username).Result
UserManager.CreateAsync(user, pass).Result
UserManager.AddToRoleAsync(user, roleName).Result

जब मैंने प्रतिस्थापित .Resultकिया .GetAwaiter().GetResult(), तो यह त्रुटि चली गई।


2

एंटिटी फ्रेमवर्क कोर एक ही DbContextउदाहरण पर चलाए जा रहे कई समानांतर संचालन का समर्थन नहीं करता है । इसमें asyncप्रश्नों के समानांतर निष्पादन और एकाधिक थ्रेड्स से कोई स्पष्ट समवर्ती उपयोग शामिल है। इसलिए, हमेशा await asyncतुरंत कॉल करता है, या DbContextसमानांतर में निष्पादित होने वाले संचालन के लिए अलग-अलग उदाहरणों का उपयोग करता है ।


1

मेरे पास एक पृष्ठभूमि सेवा है जो एक तालिका में प्रत्येक प्रविष्टि के लिए एक क्रिया करती है। समस्या यह है, कि अगर मैं DbContext के एक ही उदाहरण पर सभी डेटा को ओवररेट और संशोधित करता हूं, तो यह त्रुटि होती है।

एक सूत्र, जैसा कि इस सूत्र में बताया गया है कि DbContext के जीवनकाल को परिवर्तित करके इसे क्षणिक बना दिया जाता है

services.AddDbContext<DbContext>(ServiceLifetime.Transient);

लेकिन क्योंकि मैं कई अलग-अलग सेवाओं में परिवर्तन करता हूं और SaveChanges()इस मामले में मेरे समाधान के लिए एक बार विधि का उपयोग करने पर उन्हें प्रतिबद्ध करता हूं।

क्योंकि मेरा कोड एक सेवा में चलता है, मैं कुछ ऐसा कर रहा था

using (var scope = Services.CreateScope())
{
   var entities = scope.ServiceProvider.GetRequiredService<IReadService>().GetEntities();
   var writeService = scope.ServiceProvider.GetRequiredService<IWriteService>();
   foreach (Entity entity in entities)
   {
       writeService.DoSomething(entity);
   } 
}

यदि यह एक साधारण अनुरोध था तो सेवा का उपयोग करने में सक्षम होने के लिए। इसलिए इस मुद्दे को हल करने के लिए मैं सिर्फ एक गुंजाइश को दो में विभाजित करता हूं, एक क्वेरी के लिए और दूसरा लेखन कार्यों के लिए जैसे:

using (var readScope = Services.CreateScope())
using (var writeScope = Services.CreateScope())
{
   var entities = readScope.ServiceProvider.GetRequiredService<IReadService>().GetEntities();
   var writeService = writeScope.ServiceProvider.GetRequiredService<IWriteService>();
   foreach (Entity entity in entities)
   {
       writeService.DoSomething(entity);
   } 
}

उस तरह, DbContext के दो अलग-अलग उदाहरणों का उपयोग किया जा रहा है।

एक और संभावित समाधान यह सुनिश्चित करना होगा, कि पुनरावृति शुरू करने से पहले रीड ऑपरेशन समाप्त हो गया है। मेरे मामले में यह बहुत व्यावहारिक नहीं है क्योंकि बहुत सारे परिणाम हो सकते हैं, जिन्हें ऑपरेशन के लिए मेमोरी में लोड करने की आवश्यकता होगी, जिन्हें मैंने पहली बार एक क्वेरी के उपयोग से बचने की कोशिश की थी।


1

सबसे पहले, अपवोट (कम से कम) अलस्मी के उत्तर। जो मुझे सही रास्ते पर ले गया।

लेकिन आप में से जो IoC कर रहे हैं, उनके लिए यहां थोड़ा गहरा गोता है।

मेरी त्रुटि (दूसरों के समान)

एक या अधिक त्रुटि हुई। (पिछले ऑपरेशन पूरा होने से पहले इस संदर्भ में एक दूसरा ऑपरेशन शुरू हुआ। यह आमतौर पर DbContext के एक ही उदाहरण का उपयोग करके अलग-अलग थ्रेड्स के कारण होता है। DbContext के साथ थ्रेडिंग समस्याओं से बचने के तरीके के बारे में अधिक जानकारी के लिए, https://go.microsoft.com देखें। / fwlink /? linkid = 2097913। )

मेरा कोड सेटअप। "बस मूल बातें" ...

public class MyCoolDbContext: DbContext{
    public DbSet <MySpecialObject> MySpecialObjects {        get;        set;    }
}

तथा

public interface IMySpecialObjectDomainData{}

और (नोट MyCoolDbContext को इंजेक्ट किया जा रहा है)

public class MySpecialObjectEntityFrameworkDomainDataLayer: IMySpecialObjectDomainData{
    public MySpecialObjectEntityFrameworkDomainDataLayer(MyCoolDbContext context) {
        /* HERE IS WHERE TO SET THE BREAK POINT, HOW MANY TIMES IS THIS RUNNING??? */
        this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);
    }
}

तथा

public interface IMySpecialObjectManager{}

तथा

public class MySpecialObjectManager: IMySpecialObjectManager
{
    public const string ErrorMessageIMySpecialObjectDomainDataIsNull = "IMySpecialObjectDomainData is null";
    private readonly IMySpecialObjectDomainData mySpecialObjectDomainData;

    public MySpecialObjectManager(IMySpecialObjectDomainData mySpecialObjectDomainData) {
        this.mySpecialObjectDomainData = mySpecialObjectDomainData ?? throw new ArgumentNullException(ErrorMessageIMySpecialObjectDomainDataIsNull, (Exception)null);
    }
}

और अंत में, मेरी बहु थ्रेडेड क्लास, एक कंसोल ऐप (कमांड लाइन इंटरफ़ेस ऐप) से कॉल की जा रही है

    public interface IMySpecialObjectThatSpawnsThreads{}

तथा

public class MySpecialObjectThatSpawnsThreads: IMySpecialObjectThatSpawnsThreads
{
    public const string ErrorMessageIMySpecialObjectManagerIsNull = "IMySpecialObjectManager is null";

    private readonly IMySpecialObjectManager mySpecialObjectManager;

    public MySpecialObjectThatSpawnsThreads(IMySpecialObjectManager mySpecialObjectManager) {
        this.mySpecialObjectManager = mySpecialObjectManager ?? throw new ArgumentNullException(ErrorMessageIMySpecialObjectManagerIsNull, (Exception)null);
    }
}

और DI बिल्डअप। (फिर से, यह एक कंसोल एप्लिकेशन (कमांड लाइन इंटरफेस) के लिए है ... जो वेब-एप्स की तुलना में थोड़ा अलग व्यवहार प्रदर्शित करता है)

private static IServiceProvider BuildDi(IConfiguration configuration) {
    /* this is being called early inside my command line application ("console application") */

    string defaultConnectionStringValue = string.Empty; /* get this value from configuration */

    ////setup our DI
    IServiceCollection servColl = new ServiceCollection()
        ////.AddLogging(loggingBuilder => loggingBuilder.AddConsole())

        /* THE BELOW TWO ARE THE ONES THAT TRIPPED ME UP.  */
        .AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
    .AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()

    /* so the "ServiceLifetime.Transient" below................is what you will find most commonly on the internet search results */
     # if (MY_ORACLE)
        .AddDbContext<ProvisioningDbContext>(options => options.UseOracle(defaultConnectionStringValue), ServiceLifetime.Transient);
     # endif

     # if (MY_SQL_SERVER)
        .AddDbContext<ProvisioningDbContext>(options => options.UseSqlServer(defaultConnectionStringValue), ServiceLifetime.Transient);
     # endif

    servColl.AddSingleton <IMySpecialObjectThatSpawnsThreads,        MySpecialObjectThatSpawnsThreads>();

    ServiceProvider servProv = servColl.BuildServiceProvider();

    return servProv;
}

जिन लोगों ने मुझे आश्चर्यचकित किया वे थे (परिवर्तन) के लिए क्षणिक

        .AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
    .AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()

ध्यान दें, मुझे लगता है कि क्योंकि IMySpecialObjectManager को "MySpecialObjectThatSpawnsThreads" में इंजेक्ट किया जा रहा था, उन वस्तुओं को इंजेक्ट किया गया जो श्रृंखला को पूरा करने के लिए क्षणिक होने के लिए आवश्यक थीं।

बिंदु ....... यह सिर्फ (मेरा) DbContext की जरूरत नहीं थी। ट्रान्सिएंट ... लेकिन DI ग्राफ़ का एक बड़ा हिस्सा।

डिबगिंग टिप:

यह रेखा:

this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);

अपने डिबगर ब्रेक प्वाइंट को वहां रखें। यदि आपके MySpecialObjectThatSpawnsThreads एन नंबर थ्रेड बना रहा है (उदाहरण के लिए 10 थ्रेड्स कहिए) ...... और वह लाइन केवल एक बार हिट हो रही है ... यह आपका मुद्दा है। आपका DbContext धागे पार कर रहा है।

बक्शीश:

मैं नीचे दिए गए वेब-ऐप्स और कंसोल-ऐप के बारे में url / लेख (ओल्डी लेकिन गुडी) को पढ़ने का सुझाव दूंगा

https://mehdi.me/ambient-dbcontext-in-ef6/

लिंक बदलने की स्थिति में यहां लेख का शीर्षक है।

शत्रु के साथ अधिकार प्राप्त करने का अधिकार 6: AN IN-DEPTH GUIDE मेहदी एल गुआदरी

मैंने इस मुद्दे को WorkFlowCore https://github.com/danielgerlag/workflow-core के साथ मारा

  <ItemGroup>
    <PackageReference Include="WorkflowCore" Version="3.1.5" />
  </ItemGroup>

नमूना कोड नीचे .. भविष्य के इंटरनेट खोजकर्ताओं की मदद करने के लिए

 namespace MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Workflows
    {
        using System;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Constants;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.MySpecialObjectInterview.Glue;
        using MyCompany.Proofs.WorkFlowCoreProof.BusinessLayer.Workflows.WorkflowSteps;

        using WorkflowCore.Interface;
        using WorkflowCore.Models;

        public class MySpecialObjectInterviewDefaultWorkflow : IWorkflow<MySpecialObjectInterviewPassThroughData>
        {
            public const string WorkFlowId = "MySpecialObjectInterviewWorkflowId";

            public const int WorkFlowVersion = 1;

            public string Id => WorkFlowId;

            public int Version => WorkFlowVersion;

            public void Build(IWorkflowBuilder<MySpecialObjectInterviewPassThroughData> builder)
            {
                builder
                             .StartWith(context =>
                    {
                        Console.WriteLine("Starting workflow...");
                        return ExecutionResult.Next();
                    })

                        /* bunch of other Steps here that were using IMySpecialObjectManager.. here is where my DbContext was getting cross-threaded */


                    .Then(lastContext =>
                    {
                        Console.WriteLine();

                        bool wroteConcreteMsg = false;
                        if (null != lastContext && null != lastContext.Workflow && null != lastContext.Workflow.Data)
                        {
                            MySpecialObjectInterviewPassThroughData castItem = lastContext.Workflow.Data as MySpecialObjectInterviewPassThroughData;
                            if (null != castItem)
                            {
                                Console.WriteLine("MySpecialObjectInterviewDefaultWorkflow complete :)  {0}   -> {1}", castItem.PropertyOne, castItem.PropertyTwo);
                                wroteConcreteMsg = true;
                            }
                        }

                        if (!wroteConcreteMsg)
                        {
                            Console.WriteLine("MySpecialObjectInterviewDefaultWorkflow complete (.Data did not cast)");
                        }

                        return ExecutionResult.Next();
                    }))

                    .OnError(WorkflowCore.Models.WorkflowErrorHandling.Retry, TimeSpan.FromSeconds(60));

            }
        }
    }

तथा

ICollection<string> workFlowGeneratedIds = new List<string>();
                for (int i = 0; i < 10; i++)
                {
                    MySpecialObjectInterviewPassThroughData currentMySpecialObjectInterviewPassThroughData = new MySpecialObjectInterviewPassThroughData();
                    currentMySpecialObjectInterviewPassThroughData.MySpecialObjectInterviewPassThroughDataSurrogateKey = i;

                    ////  private readonly IWorkflowHost workflowHost;
                    string wfid = await this.workflowHost.StartWorkflow(MySpecialObjectInterviewDefaultWorkflow.WorkFlowId, MySpecialObjectInterviewDefaultWorkflow.WorkFlowVersion, currentMySpecialObjectInterviewPassThroughData);
                    workFlowGeneratedIds.Add(wfid);
                }

0

मुझे वही संदेश मिला। लेकिन यह मेरे मामले में कोई मतलब नहीं है। मेरा मुद्दा यह है कि मैं गलती से एक "NotMapped" संपत्ति का उपयोग करता हूं। यह शायद केवल कुछ मामलों में लाइनक सिंटैक्स या मॉडल वर्ग की त्रुटि का मतलब है। त्रुटि संदेश भ्रामक लगता है। इस संदेश का मूल अर्थ यह है कि आप एक ही अनुरोध में एक से अधिक बार एक ही dbcontext पर async कॉल नहीं कर सकते।

[NotMapped]
public int PostId { get; set; }
public virtual Post Post { get; set; }

आप इस लिंक को विस्तार से देख सकते हैं, https://www.softwareblogs.com/Posts/Details/5/error-a-second-operation-started-on-this-context-before-a-prepret-operation-completed


0

जब FirstOrDefaultAsync() कोड में नीचे async विधि का उपयोग करने का प्रयास करता हूं तो मुझे वही समस्या मिली । और जब मैंने तय किया FirstOrDefault()- समस्या हल हो गई!

_context.Issues.Add(issue);
        await _context.SaveChangesAsync();

        int userId = _context.Users
            .Where(u => u.UserName == Options.UserName)
            .FirstOrDefaultAsync()
            .Id;
...

2
यह FirstOrDefault () या FirstOrDefaultAsync () से संबंधित नहीं है। यह dbContext के उपयोग के बारे में है।
सजद्रे

0

मैं उस त्रुटि IQueryableको एक विधि में पारित करके प्राप्त करने में कामयाब रहा , फिर उसी संदर्भ में एक अन्य क्वेरी के हिस्से के रूप में उस IQueryable 'सूची' का उपयोग किया।

public void FirstMethod()
{
    // This is returning an IQueryable
    var stockItems = _dbContext.StockItems
        .Where(st => st.IsSomething);

    SecondMethod(stockItems);
}

public void SecondMethod(IEnumerable<Stock> stockItems)
{
    var grnTrans = _dbContext.InvoiceLines
        .Where(il => stockItems.Contains(il.StockItem))
        .ToList();
}

उस होने को रोकने के लिए मैंने यहाँ दृष्टिकोण का इस्तेमाल किया और कॉल को बदलकर दूसरी विधि को पारित करने से पहले उस सूची को भौतिक कर SecondMethodदियाSecondMethod(stockItems.ToList()


इससे समस्या हल हो गई, लेकिन क्या इससे प्रदर्शन धीमा नहीं होगा, क्या कोई वैकल्पिक समाधान है?
धीरज कुमार

0

मेरे मामले में मैं ब्लेज़र में एक टेम्पलेट घटक का उपयोग करता हूं।

 <BTable ID="Table1" TotalRows="MyList.Count()">

समस्या घटक हेडर में एक विधि (गणना) को बुला रही है। समस्या को हल करने के लिए मैंने इसे इस तरह बदला:

int total = MyList.Count();

और बादमें :

<BTable ID="Table1" TotalRows="total">

0

मुझे पता है कि इस मुद्दे को दो साल पहले पूछा गया था, लेकिन मेरे पास सिर्फ यह मुद्दा था और मैंने जो फिक्स इस्तेमाल किया था, वह वास्तव में मदद करता है।

यदि आप एक ही संदर्भ के साथ दो प्रश्न कर रहे हैं - तो आपको इसे हटाने की आवश्यकता हो सकती है AsNoTracking। यदि आप उपयोग करते हैं AsNoTrackingतो आप प्रत्येक रीड के लिए एक नया डेटा-रीडर बना रहे हैं। दो डेटा रीडर एक ही डेटा नहीं पढ़ सकते हैं।


0

मेरे मामले में मैं एक लॉक का उपयोग कर रहा था जो प्रतीक्षा के उपयोग की अनुमति नहीं देता है और जब आप एक एसिंक्स का इंतजार नहीं करते हैं तो संकलक चेतावनी नहीं बनाता है।

समस्या:

lock (someLockObject) {
    // do stuff
    context.SaveChangesAsync();
}

// some other code somewhere else doing await context.SaveChangesAsync() shortly after the lock gets the concurrency error

तय: लॉक के अंदर एस्क्वायर के लिए प्रतीक्षा करें इसे एक .Wait () के साथ अवरुद्ध करके

lock (someLockObject) {
    // do stuff
    context.SaveChangesAsync().Wait();
}

0

एक अन्य संभावित मामला: यदि आप कनेक्शन डायरेक्ट का उपयोग करते हैं, तो बंद करना न भूलें। मुझे मनमाने ढंग से SQL क्वेरी को निष्पादित करने की आवश्यकता थी, और परिणाम पढ़ें। यह एक त्वरित फिक्स था, मैं डेटा क्लास को परिभाषित नहीं करना चाहता था, "सामान्य" SQL कनेक्शन सेट नहीं करता था। तो बस के रूप में मैं EFC डेटाबेस कनेक्शन पुन: उपयोग किया var connection = Context.Database.GetDbConnection() as SqlConnection। सुनिश्चित करें कि आप करने connection.Close()से पहले कॉल करें Context.SaveChanges()


-2

यदि आपका तरीका कुछ वापस लौट रहा है, तो आप इस त्रुटि .Resultको नौकरी के अंत तक डाल सकते हैं और .Wait()यदि यह कुछ भी वापस नहीं करता है।


-6

मैं बस इसे फिर से काम करने में कामयाब रहा। यह बहुत समझ में नहीं आता है, लेकिन यह काम किया:

  1. StartUp से Hangfire निकालें (मैं वहां अपना काम बना रहा था)
  2. हैंगफ़ायर डेटाबेस को हटा दिया गया
  3. सर्वर को पुनरारंभ किया

मैं बाद में और जाँच करूँगा लेकिन जिस विधि से मैंने हैंगफ़ायर के साथ कॉल किया है वह DBContext प्राप्त करता है और यही संभव कारण है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.