C# 使用DbContext时无法分隔代码

C# 使用DbContext时无法分隔代码,c#,asp.net,entity-framework,asp.net-core,solid-principles,C#,Asp.net,Entity Framework,Asp.net Core,Solid Principles,我总是尽可能地分离代码。我对ASP.NET Core相当陌生,但所有语言的代码原则和软件设计模式都是相同的,然而,当使用实体框架时,有一些问题困扰着我,或者我不知道如何处理 在我的应用程序中,我有用户,这些用户当然是在注册时创建的。用户可以将特定项目添加到其库存中,并请求其他用户共享项目 因此,我有一个SharingRequests表,其中包含诸如userlowerId,UserLenderId,InventoryItemId等信息 当我现在想要创建一个共享请求并将用户分配给它时,我必须在同一个

我总是尽可能地分离代码。我对ASP.NET Core相当陌生,但所有语言的代码原则和软件设计模式都是相同的,然而,当使用实体框架时,有一些问题困扰着我,或者我不知道如何处理

在我的应用程序中,我有用户,这些用户当然是在注册时创建的。用户可以将特定项目添加到其库存中,并请求其他用户共享项目

因此,我有一个
SharingRequests
表,其中包含诸如
userlowerId
UserLenderId
InventoryItemId
等信息

当我现在想要创建一个共享请求并将用户分配给它时,我必须在同一个上下文中创建所有共享请求。例如,如果我这样做

MethodA: 
await using (var context = new DbContext())
{
    User user = context
        .Users
        .Where(u => u.Id == userId)
        .First();
}

methodB(user);
我得到一个错误,用户已经存在于数据库中,并且由于重复密钥,它无法创建新条目

在谷歌搜索这个问题后,我发现这是,因为我有多个数据库上下文,而第二个上下文不知道第一个

然而,这意味着,我需要的每个实体,需要加载的实体等等,都需要在一个
中等待使用(var context=new DbContext())

我看不出如何用这个限制逻辑地分离代码。这迫使我有一种做太多事情的方法

为什么不可能有一个方法来获取用户,另一个方法来构建共享请求(另一个方法来进行验证)等等


我是不是完全错过了什么?我无法想象,由于重复密钥问题,必须以这种方式构建应用程序。

是的,您缺少很多,首先将db上下文注入控制器构造函数并在startup.cs中注册,然后使用一个方法获取用户并返回它。它与实体框架无关,只是知道代码是如何工作的,并发布您的方法签名

你如何有多个上下文?它们看起来一模一样。你听说过工作单元模式吗

该错误与数据库上下文无关,您正在尝试创建一个已经存在的用户


不要使用first始终使用firstordefault。你应该去看看codewithmosh,他有一门实体框架课程。不要将干净代码与功能代码混淆。您必须学习ef的基础知识,才能对其应用干净的代码规则。按照路径进行操作,使其正常工作,然后进行清理。

您需要使用依赖项注入
Services.AddDbContext(…)
然后在包含各种方法的类中注入
DbContext
,当我对上下文使用DI时,我不必将所有内容都放在一个db Context Wait语句中?不。DI系统将为YouTunks处理它。使用DI,现在我可以毫无问题地将其分离。实际上,我已经为DI注册了DBContext,但只在类中使用它,而不是在
控制器中使用它。我还有一个
DBContextFactory
,所以我可以在单元测试中模拟它。但是,我不知道我是如何尝试创建一个已经存在的用户的,因为我唯一要添加到上下文中的是
context.SharingRequests.AddAsync(sharingRequest)newdbcontext
而不是使用DI方法。那是我的错,我认为必须这样做。现在,我已经改变了它,我可以分开它没有任何问题。非常感谢。别担心。如果要模拟和单元测试,请使用存储库模式。但是,您应该测试控制器逻辑,而不仅仅是您的存储库,并使用内存中的数据库。为每个实体创建一个单独的存储库,而不是通用存储库,因为我过去犯过这个错误,这样可以更容易地调试。是的,我已经为InventoryItem和Inventory以及其他(用户、共享等)创建了存储库。我将使用带有endtest.io的sqlite db(或e2e测试)进行功能/集成测试的控制器(但将来会用到它)。:)谢谢你的交流!您可以使用内存中的datatabse来复制sql server或您正在使用的任何数据库,如果使用sql lite无法正确测试它,则使用不同类型的数据库与不同类型的数据库进行比较。SQLLite并没有大型数据库的所有功能,它并不是一对一测试。
MethodB:
await using (var context = new DbContext())
{
    Item item = context
        .Items
        .Where(i => i.Id == itemId)
        .First();

    SharingRequest sharingRequest = new SharingRequest();
    sharingRequest.Item = item;
    sharingRequest.User = user;

    context.SharingRequests.AddAsync(sharingRequest);
    context.SaveChangesAsync();
}