সত্তা ফ্রেমওয়ার্ক কোর: পূর্ববর্তী ক্রিয়াকলাপটি শেষ হওয়ার আগে এই প্রসঙ্গে দ্বিতীয় ক্রিয়াকলাপ শুরু হয়েছিল


98

সত্তা ফ্রেমওয়ার্ক কোর ব্যবহার করে আমি একটি এএসপি.নেট কোর 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;
    }

আমি কিছুটা হারিয়েছি বিশেষত কারণ এটি স্থানীয়ভাবে চালানোর সময় এটি কাজ করে তবে আমি যখন আমার স্টেজিং সার্ভারে (আইআইএস 8.5) স্থাপন করি তখন এটি আমার এই ত্রুটিটি পায় এবং এটি স্বাভাবিকভাবে কাজ করে। আমি আমার একটি মডেলের সর্বাধিক দৈর্ঘ্য বাড়ানোর পরে ত্রুটিটি উপস্থিত হতে শুরু করে। আমি সংশ্লিষ্ট ভিউ মডেলের সর্বাধিক দৈর্ঘ্যও আপডেট করেছি। এবং আরও অনেক তালিকার পদ্ধতি রয়েছে যা খুব অনুরূপ এবং তারা কাজ করছে।

আমার একটি হ্যাংফায়ার কাজ চলছে, কিন্তু এই কাজটি একই সত্তা ব্যবহার করে না। এটাকেই আমি প্রাসঙ্গিক মনে করতে পারি। এর কারণ হতে পারে এমন কোনও ধারণা?


4
পরীক্ষা করে দেখুন এই
বার্কে

4
@ বার্কে আমি এটি এবং অন্যান্য অনেক অনুরূপ প্রশ্ন দেখেছি এবং তাদের চেষ্টা করেছি। আমার পদ্ধতিটি অ্যাসিঙ্ক ছিল এবং আমি এই সমস্যাগুলি এড়াতে এটি সিঙ্ক করেছিলাম। আমি ম্যাপিংটি সরিয়ে দেওয়ার চেষ্টাও করেছি, .ToPagedList অপসারণের চেষ্টাও করেছি এটি ত্রুটি ছুঁড়ে চালিয়ে যেতে থাকে।
আন্দ্রে লুইজ

পুরো স্ট্যাক ট্রেস দেখতে ভাল লাগবে
এভক

এবং একাধিক সক্রিয় ফলাফল সক্ষম হয়েছে কিনা তা জানতে
জে

একই সমস্যা হ'ল আমি আবিষ্কার করেছি যে আমার ডাটাবেস টেবিলটিতে নালাম পূর্ণসংখ্যা রয়েছে। যত তাড়াতাড়ি আমি আমার সত্তার মডেল বৈশিষ্ট্যগুলিকে ন্যূনতম ইন্টের সাথে মেলে সেট করার সাথে সাথে এটি সমস্ত কাজ করা শুরু করেছিল, বার্তাটি আমার জন্য বিভ্রান্তিকর ছিল ...!
সর্বদা

উত্তর:


98

আমি নিশ্চিত না যে আপনি নিজের ডিবি কনটেক্সট যেখানে কখনও এটি ব্যবহার করা যেতে পারে সমাধান করতে আপনি IoC এবং নির্ভরতা ইনজেকশন ব্যবহার করছেন কিনা। আপনি যদি করেন এবং আপনি .NET কোর (বা অন্য কোনও আইওসি-কনটেইনার) থেকে নেটিভ আইওসি ব্যবহার করছেন এবং আপনি এই ত্রুটিটি পাচ্ছেন, তবে আপনার ডিবিকন্টেক্সটটিকে ট্রান্সিয়েন্ট হিসাবে নিবন্ধন করতে ভুলবেন না। কর

services.AddTransient<MyContext>();

বা

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

পরিবর্তে

services.AddDbContext<MyContext>();

অ্যাডডিবিকন্টেক্সট প্রসঙ্গটি স্কোপড হিসাবে যুক্ত করে, যা একাধিক থ্রেডের সাথে কাজ করার সময় ঝামেলা সৃষ্টি করতে পারে।

এছাড়াও ASYNC / অপেক্ষায় রয়েছেন অপারেশন যখন ASYNC ল্যামডা এক্সপ্রেশন ব্যবহার করে, এই আচরণ হতে পারে।

এটিকে ক্ষণস্থায়ী হিসাবে যুক্ত করার সাথে এর ডাউনসাইডও রয়েছে। আপনি প্রসঙ্গটি ব্যবহার করছেন এমন একাধিক শ্রেণীর উপরে কিছু সত্তায় পরিবর্তন করতে পারবেন না কারণ প্রতিটি শ্রেণি আপনার ডিবি কনটেক্সট এর নিজস্ব উদাহরণ পাবে।

এর সহজ ব্যাখ্যা হ'ল DbContextবাস্তবায়ন থ্রেড-সেফ নয়। আপনি এই সম্পর্কে আরও পড়তে পারেন এখানে


4
আমি যখন ক্ষণস্থায়ী ব্যবহার করি তখন আমি নিম্নলিখিত সংযোগ ত্রুটিগুলি (বন্ধ বা নিষ্পত্তি) পেতে পারি 'ওমনিসোস.ডাটাএ্যাকসেস.মোডেলস.ওমনি সার্ভিসডিবি কনটেক্সট'। সিস্টেম.অজেক্টডিস্পোজড এক্সপ্লেশন: ডিসপোজড অবজেক্টে অ্যাক্সেস করা যায় না। এই ত্রুটির সাধারণ কারণটি একটি প্রসঙ্গটি নিষ্পত্তি করে যা নির্ভরতা ইনজেকশন থেকে সমাধান করা হয়েছিল এবং পরে আপনার অ্যাপ্লিকেশনে একই প্রসঙ্গ উদাহরণটি অন্য কোথাও ব্যবহার করার চেষ্টা করছে। আপনি যদি প্রসঙ্গে ডেস্পোজ () কল করতে বা কোনও ব্যবহারের বিবৃতিতে প্রসঙ্গটি মোড়ানো করে থাকেন তবে এটি ঘটতে পারে। ... অবজেক্টের নাম: 'AsyncDisposer'।
ডেভিড

4
হাই ডেভিড! আমি অনুমান করি যে আপনি Task.Run(async () => context.Set...)এটির অপেক্ষায় না রেখে বা ফলাফলটির অপেক্ষা না করে কোনও স্কোপড ডিবি প্রসঙ্গ তৈরি না করে ব্যবহার করছেন । এর অর্থ এটি অ্যাক্সেস করার সময় আপনার প্রসঙ্গটি ইতিমধ্যে নিষ্পত্তি হয়ে গেছে। আপনি যদি মাইক্রোসফ্ট ডিআই-তে থাকেন তবে আপনাকে অবশ্যই তার মধ্যে নির্ভরতার সুযোগ তৈরি করতে হবে Task.Run। এই লিঙ্কগুলিও পরীক্ষা করে দেখুন। stackoverflow.com/questions/45047877/... docs.microsoft.com/en-us/dotnet/api/...
alsami

4
পূর্বে উল্লিখিত হিসাবে, আপনি অপেক্ষা কীওয়ার্ড সহ অ্যাসিঙ্ক পদ্ধতিতে কল করতে মিস করলে, আপনি এই সমস্যার মুখোমুখি হবেন।
ইয়েনেনিফার

4
এটি সূক্ষ্ম হতে পারে, তবে পরিস্থিতিগুলির সংক্ষিপ্তসার ছাড়াই ক্ষণিকের ক্ষণিকের ব্যবহারের চেয়ে কাঙ্ক্ষিত আজীবন এবং ডেটা অ্যাক্সেসের রেজোলিউশনের সুযোগ সম্পর্কে আরও চিন্তাশীল হতে হবে। আসলে, আমি এটিকে বিরল বিবেচনা করব যে কেউ একটি ডেটা প্রসঙ্গে ট্রান্সিয়েন্ট চাইবে। যদি কাজের ইউনিটের কাজের সুযোগ কোনও একক ডেটা অপারেশনের চেয়ে বেশি জড়িত থাকে তবে লেনদেনের সুযোগটি এর চেয়ে আরও বেশি হওয়া উচিত। আপনার ডেটা প্রসঙ্গে সমাধানের ক্ষেত্রে আপনার কাজের ইউনিটের সুযোগটি মিরর করা উচিত। এটি এমন একটি বিষয় যা এর মাধ্যমে চিন্তা করা উচিত এবং এটি কোনও এক-আকারের ফিট-সব উত্তর নয়।
ডেভ রায়েল

4
@ সালামি আপনি আমার নায়ক 6 ঘন্টা বেদনাদায়ক ডিবাগিং। এই ছিল সমাধান। অন্য কেউ যদি আইবিটিপি কনটেক্সট অ্যাকসেসরটিকে ডিবিকন্টেক্সটে ইনজেকশন দিচ্ছেন এবং দাবিগুলি শূন্য হয়, তবে এটি সমাধান। আপনাকে অনেক ধন্যবাদ মানুষ।
jcmontx

62

কিছু ক্ষেত্রে, কীওয়ার্ড ছাড়াই একটি অ্যাসিঙ্ক পদ্ধতিতে কল করার সময় এই ত্রুটি ঘটে থাকে await, যা awaitপদ্ধতি কলের আগে যুক্ত করে কেবল সমাধান করা যায় । তবে উত্তরটি উল্লিখিত প্রশ্নের সাথে সম্পর্কিত নাও হতে পারে তবে এটি অনুরূপ ত্রুটি সমাধানে সহায়তা করতে পারে।


4
এটা আমার সাথে ঘটেছিল। পরিবর্তন First()করার জন্য await / FirstAsync()কাজ করেন।
গিলহার্ম 20

উপনোট। এছাড়াও jimlynn.wordpress.com/2017/11/16/… দেখুন জিম লিন "সত্তা ফ্রেমওয়ার্ক এর ত্রুটি: একটি সম্পূর্ণ অপারেশন সম্পন্ন হওয়ার আগে এই বিষয়বস্তুতে শুরু হয়েছে AN
গ্রানাডা কোডার

এর জন্য ধন্যবাদ! এটি হ'ল আমার সমস্যা ... একটি অ্যাসিঙ্ক এমডেথোডের জন্য অপেক্ষা করতে ভুলে গেছেন Forg
এক্সলওক

আমার সাথেও ঘটেছিল, এবং এই মন্তব্যটি যেমন খুঁজে পেয়েছি সেখানে আমি কোনও অনুপস্থিত প্রত্যাশাকে ভুলে গেছি। আমি একবার এটি খুঁজে পেয়েছি, সমস্যার সমাধান হয়ে গেছে।
জিয়ন হাই

এটি আমার জন্য কাজ করেছে, অনেক অনেক ধন্যবাদ
zoha_sh

43

ব্যতিক্রমটির অর্থ _contextএকই সময়ে দুটি থ্রেড দ্বারা ব্যবহৃত হচ্ছে; হয় একই অনুরোধে দুটি থ্রেড, বা দুটি অনুরোধ দ্বারা।

আপনার _contextঘোষণা স্থির হয়? এটা হওয়া উচিত নয়।

অথবা GetClientsআপনি আপনার কোডের অন্য কোথাও থেকে একই অনুরোধে একাধিকবার কল করছেন ?

আপনি ইতিমধ্যে এটি করছেন, তবে আদর্শভাবে, আপনি আপনার জন্য নির্ভরতা ইনজেকশন ব্যবহার করছেন DbContext, যার অর্থ আপনি AddDbContext()আপনার স্টার্টআপ.সি ব্যবহার করছেন এবং আপনার নিয়ামক নির্মাতাকে এটির মতো দেখতে পাবেন:

private readonly MyDbContext _context; //not static

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

যদি আপনার কোডটি এটির মতো না হয় তবে আমাদের দেখান এবং সম্ভবত আমরা আরও সাহায্য করতে পারি।


4
সম্ভবত এটি আমার কাজ। আমি সমাধান করতে পরিচালিত, আমার উত্তর দেখুন। তবে আমি আপনাকে সঠিক হিসাবে চিহ্নিত করছি
আন্দ্রে লুইজ

আমার কোডটি ঠিক এর মতো এবং আমরা প্রায়শই ট্র্যাক করি "পূর্ববর্তী অ্যাসিনক্রোনাস অপারেশন শেষ হওয়ার আগে এই প্রসঙ্গে দ্বিতীয় অপারেশন শুরু হয়েছিল track এই প্রসঙ্গে অন্য কোনও পদ্ধতি কল করার আগে কোনও অ্যাসিনক্রোনাস অপারেশন সম্পন্ন হয়েছে তা নিশ্চিত করার জন্য 'অপেক্ষা' ব্যবহার করুন Any কোনও উদাহরণ সদস্য নয় থ্রেড নিরাপদ থাকার গ্যারান্টিযুক্ত -
এনমাথুর

@ এনএমথুর আপনি কি _contextঅন্য থ্রেডে নিজের অবজেক্টটি ব্যবহার করছেন ? যেমন একটি Task.Run()উদাহরণস্বরূপ ভিতরে ?
গ্যাব্রিয়েল লুসি

@ গ্যাব্রিয়েললুচি আমার সমস্ত পদ্ধতি নীচের মত অ্যাসিঙ্ক, এটি সমস্যার কারণ হবে। এই বিষয় সম্পর্কে আমার জ্ঞান খুব কম। এই আচরণগুলি বোঝার জন্য কোথায় এবং কী আমার বিস্তারিত পড়তে হবে তা আপনি কী পরামর্শ দিতে পারেন? পাবলিক অ্যাসিঙ্ক টাস্ক <লিস্ট <আইটেম>> গেটইটেমস (ইন অর্ডারআইডি) {তালিকা <আইটেম> আইটেমগুলি = প্রত্যাশী _ কনটেক্সট. আইটেম.কখন (x => x.OrderId == অর্ডারআইডি) .ToListAsync (); ফেরত মালামাল; }
এনমাথুর

পছন্দ করেছেন কেবল নিশ্চিত হন যে আপনি সর্বদা awaitঅ্যাসিঙ্ক পদ্ধতি ব্যবহার করছেন । আপনি যদি ব্যবহার না করেন তবে আপনি awaitঅজান্তেই মাল্টি-থ্রেডিংয়ে যেতে পারেন।
গ্যাব্রিয়েল লুসি

11
  • কোডটি এই লাইনটি আমার স্টার্টআপ.সি ফাইলগুলিতে ব্যবহার করে আমার সমস্যার সমাধান করুন।
    ক্ষণস্থায়ী পরিষেবা যুক্ত করার অর্থ হ'ল প্রতিবার পরিষেবাটি অনুরোধ করা হচ্ছে, আপনি যখন নির্ভরতা ইনজেকশন নিয়ে কাজ করছেন তখন একটি নতুন উদাহরণ তৈরি হয়

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

মাল্টি-ইউজার তাত্ক্ষণিক লেনদেনের সংখ্যা বেশি এমন ক্ষেত্রে এই পদ্ধতিটি সমস্যা সৃষ্টি করবে।
hakantopuz

11

আমারও একই সমস্যা ছিল এবং এটি প্রমাণিত হয়েছিল যে পিতামাতাদের পরিষেবাটি সিনজেলটন। সুতরাং প্রসঙ্গটি স্বয়ংক্রিয়ভাবে সিঞ্জেলটনও হয়ে উঠেছে। যদিও ডিআই-তে লাইফ টাইম স্কোপড হিসাবে ঘোষিত হয়েছিল।

অন্য লাইফটাইমগুলির সাথে অন্যটিতে ইনজেকশন সেবা service

  1. স্কেলড এবং অস্থায়ী পরিষেবাগুলিকে কখনও সিঙ্গলটন পরিষেবাতে ইনজেক্ট করবেন না। (এটি কার্যকরভাবে ক্ষণস্থায়ী বা স্কোপড পরিষেবাটিকে সিঙ্গলটনে রূপান্তর করে))

  2. ক্ষণস্থায়ী পরিষেবাগুলিতে ক্ষণস্থায়ী পরিষেবাগুলিকে কখনই ইনজেক্ট করবেন না (এটি ক্ষণস্থায়ী পরিষেবাটিকে স্কোপে রূপান্তর করে))


এটি আমার সমস্যাটি হুবহু ছিল
জোনেসোপলিস

এটি আমার সমস্যাও ছিল। আমি সিঙ্গেলটন হিসাবে হ্যান্ডলার ক্লাস, এবং অস্থায়ী হিসাবে DbContext নিবন্ধিত ছিল। হ্যান্ডলারটি যতবার আঘাত
হানে ততবারই

6

আমি মনে করি এই উত্তরটি এখনও কাউকে সাহায্য করতে পারে এবং বহুবার সাশ্রয় করতে পারে। আমি পরিবর্তন করে একটি অনুরূপ সমস্যা সমাধান IQueryableকরার জন্য List(অথবা অ্যারে, সংগ্রহ ... করার জন্য)।

উদাহরণ স্বরূপ:

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

প্রতি

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

4
আইএমএইচও, এই উত্তরটি বিয়োগ পয়েন্টের প্রাপ্য নয়, এটি কেবল খারাপভাবে প্রকাশ করা হয়েছে। .ToList () প্রকৃতপক্ষে বেশিরভাগ সমস্যার সমাধান করে "দ্বিতীয় অপারেশন ..." এর কারণে যা তা প্রকাশের তাত্ক্ষণিক মূল্যায়নকে বাধ্য করে। এইভাবে কোনও সারি প্রসঙ্গ ক্রিয়াকলাপ নেই।
ভাসিলাগ

4
এটি আমার ক্ষেত্রে বিষয়টি ছিল। আমার কাছে xxx.Contains (z.prop) ছিল যেখানে কোয়েরির একটি ধারা রয়েছে। পূর্ববর্তী ক্যোয়ারী থেকে এক্সএক্সএক্স একটি আলাদা ইন্ট [] অ্যারে সমাধান করা উচিত বলে মনে করা হয়েছিল। দুর্ভাগ্যক্রমে, দ্বিতীয় ক্যোয়ারের আঘাতের সময়ে, এক্সএক্সএক্সএক্স এখনও আইকুয়েরেবল ছিল। দ্বিতীয় ক্যোয়ারির আগে xxx.ToArray () যুক্ত করা আমার সমস্যাটি স্থির করেছে।
জেসন বুটেরা

5

আমারও ত্রুটি ছিল এটি ঘটেছে কারণ আমি তার public async void ...পরিবর্তে নির্মিত একটি পদ্ধতি বলেছিলাম public async Task ...


2

আমি একই সমস্যার মুখোমুখি হয়েছি কিন্তু কারণটি উপরে তালিকাভুক্ত বিষয়গুলির মধ্যে কোনওটিই ছিল না। আমি একটি টাস্ক তৈরি করেছি, টাস্কের ভিতরে একটি সুযোগ তৈরি করেছি এবং ধারককে একটি পরিষেবা পেতে বলেছি। এটি দুর্দান্ত কাজ করেছে তবে আমি কার্যের অভ্যন্তরে দ্বিতীয় পরিষেবাটি ব্যবহার করেছি এবং আমি এটি নতুন সুযোগের জন্য জিজ্ঞাসা করতে ভুলে গিয়েছিলাম। তার কারণে, 2 য় পরিষেবাটি একটি ডিবি কনটেক্সট ব্যবহার করছে যা ইতিমধ্যে নিষ্পত্তি হয়েছিল।

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 এর জীবনকালটিকে পছন্দ হিসাবে সংজ্ঞা দিয়ে ক্ষণস্থায়ী করে তোলা

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);
   } 
}

এর মতো, কার্যকরভাবে ডিবি কনটেক্সট ব্যবহারের দুটি পৃথক দৃষ্টান্ত রয়েছে।

আরেকটি সম্ভাব্য সমাধান হ'ল এটি নিশ্চিত করা, যে পুনরাবৃত্তিটি শুরু করার আগে পঠন অপারেশনটি শেষ হয়ে গেছে। এটি আমার ক্ষেত্রে খুব তাত্পর্যপূর্ণ নয় কারণ প্রচুর ফলাফল হতে পারে যে অপারেশনটির জন্য সমস্তই মেমোরিতে লোড করা দরকার যা আমি প্রথমে কোয়েরিয়েবল ব্যবহার করে এড়াতে চেষ্টা করেছি।


1

প্রথমে আলসামির উত্তর আপভোট করুন। এটি আমাকে সঠিক পথে পেয়েছে।

তবে আপনারা যারা আইওসি করছেন তাদের জন্য এখানে কিছুটা গভীর ডাইভ রয়েছে।

আমার ত্রুটি (অন্যদের মতো)

এক বা একাধিক ত্রুটি ঘটেছে। (একটি দ্বিতীয় অপারেশন পূর্ববর্তী অপারেশন সম্পন্ন করার আগে এই প্রেক্ষাপটে শুরু। সাধারণত বিভিন্ন থ্রেড DbContext একই উদাহরণস্বরূপ ব্যবহার দ্বারা ঘটিত হয়। কিভাবে DbContext সমস্যা থ্রেডিং এড়াতে সম্পর্কে আরো তথ্যের জন্য, দেখুন https://go.microsoft.com / fwlink /? linkid = 2097913। )

আমার কোড সেটআপ। "শুধু বেসিক" ...

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

এবং

public interface IMySpecialObjectDomainData{}

এবং (নোট মাইকুলডিবি কনটেক্সট ইনজেকশন দেওয়া হচ্ছে)

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);
    }
}

এবং ডিআই বিল্ডআপ। (আবার এটি কনসোল অ্যাপ্লিকেশনটির জন্য (কমান্ড লাইন ইন্টারফেস) ... যা ওয়েব-অ্যাপ্লিকেশনগুলির তুলনায় কিছুটা ভিন্ন আচরণ দেখায়)

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>()

দ্রষ্টব্য, আমি মনে করি যেহেতু আইএমআইস্পেশিয়ালঅবজেক্টম্যানেজারকে "মাইস্পেশিয়ালবজেক্টট্যাটস্পেনস ট্র্যাডস" ইনজেক্ট করা হয়েছিল, সেই ইঞ্জেকশনযুক্ত বিষয়গুলি চেইনটি সম্পূর্ণ করার জন্য ট্রান্সিয়েন্ট হওয়া দরকার।

বিষয়টি হ'ল ....... এটি কেবল (আমার) ডিবি কনটেক্সটই ছিল না যা প্রয়োজন rans ট্রান্সিয়েন্ট ... তবে ডিআই গ্রাফের একটি বড় অংশ।

ডিবাগিং টিপ:

এই লাইন:

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

আপনার ডিবাগার ব্রেক পয়েন্টটি সেখানে রাখুন। যদি আপনার মাইস্পেশিয়ালঅবজেক্টট্যাটস্প্যানস থ্রেডগুলি এন সংখ্যায় থ্রেড তৈরি করে (উদাহরণস্বরূপ 10 টি থ্রেড বলুন) ...... এবং সেই লাইনটি কেবল একবার আঘাত করা হবে ... এটি আপনার সমস্যা। আপনার DbContext থ্রেড অতিক্রম করছে।

বোনাস:

আমি এই নীচের url / আর্টিকেলটি পড়ার পরামর্শ দেব (পুরাতন তবে গুডি) পার্থক্যগুলি ওয়েব-অ্যাপস এবং কনসোল-অ্যাপস সম্পর্কে about

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

লিঙ্ক পরিবর্তিত হয় নিবন্ধের শিরোনাম এখানে।

এন্টিটির ফ্রেম ওয়ার্কের সাথে সঠিকভাবে ডব্লিকন্টেক্সট পরিচালনা করা:: একটি ইন-ডেপথ গাইড মেহদি এল গুয়েদারি

আমি এই সমস্যাটিকে ওয়ার্কফ্লোকোর 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

আমি একই বার্তা পেয়েছি। তবে এটি আমার ক্ষেত্রে কোনও ধারণা রাখছে না। আমার সমস্যাটি হ'ল আমি ভুল করে একটি "নটম্যাপড" সম্পত্তি ব্যবহার করি। এটি সম্ভবত কিছু ক্ষেত্রে লিনাক সিনট্যাক্স বা মডেল বর্গের একটি ত্রুটি বোঝায়। ত্রুটি বার্তাটি বিভ্রান্তিমূলক বলে মনে হচ্ছে। এই বার্তার আসল অর্থ হ'ল আপনি একই অনুরোধে একাধিকবার 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-st সূত্র- ও- এই-context-before-a- পূর্বত- আপেশন- কমপ্লিট


0

FirstOrDefaultAsync() নীচের কোডে অ্যাসিঙ্ক পদ্ধতিতে ব্যবহার করার চেষ্টা করার সময় আমি একই সমস্যা পেয়েছি । আর আমি যখন স্থির করলাম FirstOrDefault()- সমস্যার সমাধান হয়ে গেল!

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

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

4
এটি মোটামুটি ফার্স্টআরডিফল্ট () বা ফার্স্টওরডিফল্ট এ্যাসেন্স () সম্পর্কিত নয় t এটি ডিবিকন্টেক্সট এর ব্যবহার সম্পর্কে about
সাজাদ্রে

0

আমি সেই 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

আমি জানি যে এই সমস্যাটি দুই বছর আগে জিজ্ঞাসা করা হয়েছিল, তবে আমি কেবল এই সমস্যাটি পেয়েছি এবং আমার ব্যবহৃত স্থিরতাটি সত্যই সহায়তা করেছিল helped

আপনি যদি একই প্রসঙ্গে দুটি ক্যোয়ারী করে থাকেন - আপনার এটিকে অপসারণ করতে হবে 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

সমাধান: লকটিকে এটিকে একটি ব্লক করে তৈরি করে ভিতরে থাকা অ্যাসিঙ্কের জন্য অপেক্ষা করুন a

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

0

আর একটি সম্ভাব্য কেস: আপনি যদি সরাসরি সংযোগটি ব্যবহার করেন তবে বন্ধ করতে ভুলবেন না। আমার নির্বিচারে এসকিউএল কোয়েরি চালানো দরকার, এবং ফলাফলটি পড়তে হবে। এটি একটি দ্রুত সমাধান ছিল, আমি কোনও ডাটা ক্লাস সংজ্ঞায়িত করতে চাই না, "সাধারণ" এসকিউএল সংযোগ স্থাপন করিনি। সুতরাং সহজভাবে আমি EFC এর ডাটাবেস সংযোগটি পুনরায় ব্যবহার করেছি var connection = Context.Database.GetDbConnection() as SqlConnection। নিশ্চিত করুন যে আপনি কল করতে connection.Close()পারার আগে আপনাকে কি Context.SaveChanges()


-2

যদি আপনার পদ্ধতিটি কোনও কিছু ফিরিয়ে দিচ্ছে .Result, তবে আপনি কাজটির শেষের দিকে রেখে এবং .Wait()যদি কোনও কিছুই ফেরত না দেয় তবে আপনি এই ত্রুটিটি সমাধান করতে পারেন ।


-6

আমি কেবল এটি আবার কাজ করতে পরিচালিত। এটি খুব বেশি বোঝায় না তবে এটি কাজ করেছে:

  1. স্টার্টআপ থেকে হ্যাংফায়ার সরান (আমি সেখানে আমার কাজ তৈরি করছিলাম)
  2. হ্যাংফায়ার ডেটাবেস মোছা হয়েছে
  3. সার্ভার পুনরায় চালু হয়েছে

আমি পরে আরও তদন্ত করব তবে হ্যাংফায়ারের সাহায্যে আমি যে পদ্ধতিটি কল করেছি তা একটি ডিবিসিএনটেক্সট পায় এবং এটিই সম্ভাব্য কারণ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.