gpt4 book ai didi

asp.net-mvc - 使用存储库模式时的多个数据库上下文

转载 作者:行者123 更新时间:2023-12-02 08:20:34 27 4
gpt4 key购买 nike

我现在有点迷茫……我从未见过关于解决问题的如此多的不同信息。但让我们从头开始。

感谢 Ninject,我正在使用 ASP.NET MVC 将存储库注入(inject) Controller 。我有 2 个简单的实体:带有已创建博客条目列表的管理员和带有一个虚拟管理字段的条目。

管理员:

public class Admin
{
[Key, ScaffoldColumn(false)]
public int Id { get; set; }

[Required(ErrorMessage = "Zły login.")]
[StringLength(20), MinLength(3)]
[RegularExpression(@"^[a-zA-Z0-9]*$", ErrorMessage = "Special characters are not allowed.")]
public string Login { get; set; }

[Required(ErrorMessage = "Złe hasło.")]
[StringLength(20, MinimumLength = 3)]
[DataType(DataType.Password)]
[Display(Name = "Hasło")]
public string Password { get; set; }

public virtual List<Entry> CreatedEntries { get; set; } // napisane aktualności przez danego admina
}

条目:

public class Entry
{
[Key, ScaffoldColumn(false)]
public int Id { get; set; }

[StringLength(200, MinimumLength = 2)]
[DataType(DataType.Text)]
[Display(Name = "Tytuł")]
public string Title { get; set; }

[Required, StringLength(2000), MinLength(3)]
[Display(Name = "Treść")]
[UIHint("tinymce_jquery_full"), AllowHtml]
public string Text { get; set; }

public virtual Admin Admin { get; set; }
}

您可能知道它的去向,因为这个问题是……stackoverflow 上的“经典”问题。

在 Controller 中,我想将一个对象绑定(bind)到另一个对象:

entry.Admin = repAdmins.GetAdmin(User.Identity.Name);

repEntries.AddEntry(entry);

在存储库中:

public void AddEntry(Entry entry)
{
db.Entries.Add(entry);
db.SaveChanges();
}

当然我不能那样做,因为著名的“实体对象不能被 IEntityChangeTracker 的多个实例引用”,这是每个存储库中具有单独的数据库上下文的结果。

当我在寻找解决方案时,我已经知道解决它的最佳方法可能是使用一个共同的上下文。然后我发现了工作单元模式。但这是真正的问题开始的时候。

  1. 在许多网站上,对此的解决方案略有不同。
  2. 存储库必须有通用的通用接口(interface)(我不想使用它,因为我不需要对每个实体进行每个 CRUD 操作,而且有时我需要有额外的方法,如“IfExists”等。 )
  3. 在一些网站上我读到不需要整个抽象,因为 Entity Framework 已经提供了抽象并且 UoW 在 DbContext 中实现(无论那意味着什么)
  4. 工作单元模式(至少从互联网上的例子来看)对我来说似乎是一个真正的痛苦......

我需要一些指导...我只学习了一年的 ASP.NET MVC。对我来说,这似乎是“形式对内容的胜利”。因为... 我只需要将一个对象绑定(bind)到另一个对象。我开始认为,当我在 Controller 中只拥有一个上下文对象时会更好,而我不需要 build 埃菲尔铁塔以实现上述目标:\但是我喜欢存储库的想法......

最佳答案

我将直接回答问题作为开场白。简单地说,您的存储库应该将上下文作为依赖项(它应该有一个构造函数来接受类型为 DbContext 的参数)。您的上下文应该由 Ninject 管理,然后注入(inject)到您的存储库和/或您的 Controller 中。这样,一切都始终使用相同的上下文。您应该在“请求”范围内执行所有这些操作,以便上下文特定于当前请求。

也就是说,我想谈谈您的其他一些观点。首先,存储库只是一种访问方法。它真的不应该依赖于实体。可以使用您不打算在特定实体上使用的方法:只是不要使用它们。但是,如果您确实想强制执行此操作,则始终可以使用通用约束和接口(interface)。例如,假设您不希望对特定实体进行更新。你可以有这样的界面:

public interface ICreateable
{
}

public interface IUpdateable : ICreateable
{
}

然后,您不应更新的实体将仅实现 ICreateable而其他实体(允许更新)将实现 IUpdateable (通过接口(interface)继承,也实现了 ICreateable )。最后,您将对存储库方法添加约束:

public void Create<TEntity>(TEntity entity)
where TEntity : class, ICreateable

public void Update<TEntity>(TEntity entity>)
where TEntity : class, IUpdateable

因为,有问题的实体只实现了 ICreatable , 它没有资格用作 Update 的类型参数, 因此无法使用该方法。

接下来,不使用 Entity Framework 的存储库/UoW 模式的建议确实是因为 Entity Framework 已经实现了这些模式。存储库模式作为一种在一个地方包含所有数据库查询逻辑(构建 SQL 语句等)的方式而存在。这就是我们在这里谈论的“抽象”。换句话说,不是在您的应用程序代码中直接构造 SQL 语句,而是将该代码抽象到存储库中。然而,这正是 Entity Framework 所做的,这就是为什么您不需要再次这样做的原因。工作单元模式作为一种编排多个存储库工作的方法而存在,允许事务之类的事情。然而,同样, Entity Framework 完成了所有这一切。

添加任何进一步抽象的唯一原因是如果您想抽象实际的提供者,即 Entity Framework 本身。例如,您可以拥有类似 IRepository 的界面然后创建类似 EntityFrameworkRepository 的实现, NHibernateRepository , WebApiRepository等。您的应用程序只会依赖于 IRepository ,然后您可以根据需要分入不同的实现。如果您不打算这样做,或者您将始终使用 Entity Framework,那么您最好直接使用您的上下文。任何进一步的抽象都只是其他需要维护的东西,对您的应用程序没有任何好处。

最后,是的,工作单元模式对每个人来说都是一个真正的痛苦,而不仅仅是你。这就是为什么我完全放弃它。我使用我称之为“真正通用的存储库”的东西,它利用通用方法和接口(interface)来处理我想扔给它的任何实体。这意味着它不仅充当存储库,而且还是工作单元。每个上下文只需要一个实例,并且它与提供者无关。有关更多信息,请查看 article I wrote on the subject在我的网站上。

关于asp.net-mvc - 使用存储库模式时的多个数据库上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37654994/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com