Đầu tiên, hãy ủng hộ (ít nhất) câu trả lời của alsami. Điều đó đã giúp tôi đi đúng đường.
Nhưng đối với những người bạn đang làm IoC, đây là một chút tìm hiểu sâu hơn.
Lỗi của tôi (giống như những người khác)
Một hoặc nhiều lỗi đã xảy ra. (Thao tác thứ hai bắt đầu trên ngữ cảnh này trước khi thao tác trước đó hoàn tất. Điều này thường do các luồng khác nhau sử dụng cùng một phiên bản của DbContext gây ra. Để biết thêm thông tin về cách tránh các sự cố về luồng với DbContext, hãy xem
https://go.microsoft.com / fwlink /? linkid = 2097913. )
Thiết lập mã của tôi. "Chỉ những điều căn bản"...
public class MyCoolDbContext: DbContext{
public DbSet <MySpecialObject> MySpecialObjects { get; set; }
}
và
public interface IMySpecialObjectDomainData{}
và (lưu ý MyCoolDbContext đang được đưa vào)
public class MySpecialObjectEntityFrameworkDomainDataLayer: IMySpecialObjectDomainData{
public MySpecialObjectEntityFrameworkDomainDataLayer(MyCoolDbContext context) {
this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);
}
}
và
public interface IMySpecialObjectManager{}
và
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);
}
}
Và cuối cùng, lớp đa luồng của tôi, được gọi từ Ứng dụng điều khiển (ứng dụng Giao diện dòng lệnh)
public interface IMySpecialObjectThatSpawnsThreads{}
và
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);
}
}
và tích lũy DI. (Một lần nữa, điều này dành cho ứng dụng bảng điều khiển (giao diện dòng lệnh) ... thể hiện hành vi hơi khác so với ứng dụng web)
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;
}
Điều làm tôi ngạc nhiên là (thay đổi thành) tạm thời cho
.AddTransient<IMySpecialObjectDomainData, MySpecialObjectEntityFrameworkDomainDataLayer>()
.AddTransient<IMySpecialObjectManager, MySpecialObjectManager>()
Lưu ý, tôi nghĩ vì IMySpecialObjectManager đã được đưa vào "MySpecialObjectThatSpawnsThreads", các đối tượng được tiêm đó cần phải là Tạm thời để hoàn thành chuỗi.
Vấn đề là ....... nó không chỉ cần DbContext (Của tôi). Transient ... mà là một phần lớn hơn của DI Graph.
Mẹo gỡ lỗi:
Đường thẳng này:
this.entityDbContext = context ?? throw new ArgumentNullException("MyCoolDbContext is null", (Exception)null);
Đặt điểm ngắt trình gỡ lỗi của bạn ở đó. Nếu MySpecialObjectThatSpawnsThreads của bạn tạo N số luồng (ví dụ như 10 luồng) ...... và dòng đó chỉ được đánh một lần ... đó là vấn đề của bạn. DbContext của bạn đang vượt qua các chủ đề.
TẶNG KEM:
Tôi khuyên bạn nên đọc url / bài viết này bên dưới (cũ nhưng tốt) về sự khác biệt giữa ứng dụng web và ứng dụng bảng điều khiển
https://mehdi.me/ambient-dbcontext-in-ef6/
Đây là tiêu đề của bài báo trong trường hợp liên kết thay đổi.
QUẢN LÝ DBC THEO CÁCH ĐÚNG VỚI KHUNG CỦA ENTITY 6: HƯỚNG DẪN BÊN TRONG Mehdi El Gueddari
Tôi gặp sự cố này với WorkFlowCore https://github.com/danielgerlag/workflow-core
<ItemGroup>
<PackageReference Include="WorkflowCore" Version="3.1.5" />
</ItemGroup>
mã mẫu bên dưới .. để giúp những người tìm kiếm trên internet trong tương lai
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));
}
}
}
và
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);
}