在我们的 Web.API 项目中,我们使用 Entity Framework 6。我们有一个 DataModel 类,其中包含 DatabaseContext。 DataModel 是一个 [ThreadStatic]
单例。
像这样:
public class DataModel
{
[ThreadStatic] private static DataModel _instance;
public static DataModel Instance => _instance ?? (_instance = new DataModel());
public DatabaseContext Context { get; private set; }
private DataModel()
{
Context = NewContext();
}
}
现在在我们的一个(部分)模型类中,我们使用这样的上下文:
public partial class Job
{
public User CreatedByUser
{
get { return DataModel.Instance.Context.Users.FirstOrDefault(d => d.Username == CreatedBy); }
}
}
我们在数据库的另一个表中查找对应的用户。这可行,但在我看来,这不是一个漂亮的解决方案。特别是如果我们计划将我们的项目迁移到 .NET Core 并对数据库上下文使用依赖注入(inject)。
我的问题是,有没有一种模式可以更优雅地解决问题?依赖注入(inject)在这里不起作用,因为 Entity Framework 生成模型对象。或者,如果我们将此代码从部分类移动到例如实用程序类?但是我们怎样才能在那里注入(inject)上下文呢?
最佳答案
您通常希望避免要求您的模型了解它们的创建和使用环境,因为这种知识应该是自上而下的,而不是自下而上的。除其他原因外,您会遇到像现在这样的设计问题。您可以尝试使用扩展方法、控制框架的反转、实用方法、pocos 等在应用程序级别设计绕过它的方法,但最终您要解决的问题只存在于您的底层数据库模式的设计不适合您的预期用途。
例如,您的Job
表有一个对创建它的用户的用户名的引用。为什么?用户名可能会更改,并且任何时候您需要该用户的其他关键属性,您都需要执行二次查找(就像您在部分类中所做的那样)。如果您改为让 Job
表维护一个指向 User
表的外键,您可以只使用 C# 端的导航属性来获取完整的用户对象,只要适当的相关实体包含在查询中。您甚至不需要部分类,作为额外的好处,您的数据库架构将变得更易于维护。
有时最好简化数据库设计以简化代码。
关于c# - 模型类中的 EF 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44701150/