सबसे पहले, अपवोट (कम से कम) अलस्मी के उत्तर। जो मुझे सही रास्ते पर ले गया।
लेकिन आप में से जो 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) {
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) {
string defaultConnectionStringValue = string.Empty;
IServiceCollection servColl = new ServiceCollection()
.AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
.AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()
# 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();
})
.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;
string wfid = await this.workflowHost.StartWorkflow(MySpecialObjectInterviewDefaultWorkflow.WorkFlowId, MySpecialObjectInterviewDefaultWorkflow.WorkFlowVersion, currentMySpecialObjectInterviewPassThroughData);
workFlowGeneratedIds.Add(wfid);
}