C# 如何抽象实体框架模型属性
我有一个这样的模型:C# 如何抽象实体框架模型属性,c#,entity-framework,C#,Entity Framework,我有一个这样的模型: public class Task : ITask { public int DocumentId { get; set; } public virtual Document Document { get; set; } public TaskType TaskType { get; } public string Value { get; } } 现在,这个类直接注册为DbContext中的DbSet。 这意味着文档属性必须是具体类型。我
public class Task : ITask
{
public int DocumentId { get; set; }
public virtual Document Document { get; set; }
public TaskType TaskType { get; }
public string Value { get; }
}
现在,这个类直接注册为DbContext
中的DbSet
。
这意味着文档
属性必须是具体类型。我希望使此代码易于测试,因此我希望将属性作为ITask
接口所需的接口。处理这个问题的一般方法是什么
我想到的一种方法是将所有此类类放在一个单独的程序集中,但这似乎有点不合适
编辑:
ITask
接口是在不同的程序集中定义的,因此它不应该知道文档的类型。接口中可以定义属性,因此您的ITask可以指定文档,如下所示:
public interface ITask {
Document Document { get; set; }
}
但是您还说您希望Document属性作为接口,这变得很棘手,因为您需要任务类中的具体类型。通用接口在这里会有所帮助
// The interfaces
public interface ITask<TDocument> where TDocument : IDocument, new() {
TDocument Document { get; set; }
}
public interface IDocument {
int Number { get; set; } // Example property
}
//The classes
public class Document : IDocument{
public int Number { get; set; } // Example property
}
public class Task : ITask<Document> {
public Document Document { get; set; }
}
// See if it works
public class Test {
private Task myTask = new Task();
public void TestMethod() {
myTask.Document.Number = 1;
}
}
//接口
公共接口ITask,其中t文档:IDocument,new(){
t文档文档{get;set;}
}
公共接口IDocument{
int Number{get;set;}//示例属性
}
//班级
公共类文档:IDocument{
公共整数{get;set;}//示例属性
}
公共类任务:ITask{
公共文档文档{get;set;}
}
//看看它是否有效
公开课考试{
私有任务myTask=新任务();
公共void TestMethod(){
myTask.Document.Number=1;
}
}
记住,在DBContext中使用具体类型
至于接口应该位于何处,相同的程序集还是它们自己的,对此有很多观点。就我个人而言,我把它们放在自己的程序集中,远离实现类。这个问题值得一读:
还有一条注释,类名任务在.Net线程库中使用,因此可能值得考虑更改它以避免潜在的混淆。接口中可以定义属性,因此您的ITask可以指定文档,如下所示:
public interface ITask {
Document Document { get; set; }
}
但是您还说您希望Document属性作为接口,这变得很棘手,因为您需要任务类中的具体类型。通用接口在这里会有所帮助
// The interfaces
public interface ITask<TDocument> where TDocument : IDocument, new() {
TDocument Document { get; set; }
}
public interface IDocument {
int Number { get; set; } // Example property
}
//The classes
public class Document : IDocument{
public int Number { get; set; } // Example property
}
public class Task : ITask<Document> {
public Document Document { get; set; }
}
// See if it works
public class Test {
private Task myTask = new Task();
public void TestMethod() {
myTask.Document.Number = 1;
}
}
//接口
公共接口ITask,其中t文档:IDocument,new(){
t文档文档{get;set;}
}
公共接口IDocument{
int Number{get;set;}//示例属性
}
//班级
公共类文档:IDocument{
公共整数{get;set;}//示例属性
}
公共类任务:ITask{
公共文档文档{get;set;}
}
//看看它是否有效
公开课考试{
私有任务myTask=新任务();
公共void TestMethod(){
myTask.Document.Number=1;
}
}
记住,在DBContext中使用具体类型
至于接口应该位于何处,相同的程序集还是它们自己的,对此有很多观点。就我个人而言,我把它们放在自己的程序集中,远离实现类。这个问题值得一读:
还有一条评论,类名任务是在.Net线程库中使用的,因此可能值得考虑更改它以避免潜在的混淆。我将仅对数据访问层使用EF模型,并为业务层创建单独的模型。数据访问层将负责将EF模型映射到业务层模型,并将其交给业务层
然后,业务层模型也可以是不可变的,这可能具有优势。此外,您还可以要求构造函数中的所有属性都不为null,然后您可以在整个业务层中依赖这些属性
当然,您可能会争辩说,要编写的代码几乎是原来的两倍。的确如此,但在我看来,it会带来更干净的代码,因此这是我的首选方法。我只会对数据访问层使用EF模型,并为业务层创建一个单独的模型。数据访问层将负责将EF模型映射到业务层模型,并将其交给业务层
然后,业务层模型也可以是不可变的,这可能具有优势。此外,您还可以要求构造函数中的所有属性都不为null,然后您可以在整个业务层中依赖这些属性
当然,您可能会争辩说,要编写的代码几乎是原来的两倍。这是真的,但在我看来,它会产生更干净的代码,因此这是我首选的方法。一个想法可以是实现文档:IDocument
,将ITask
定义为ITask{IDocument getDocumnet();}
,最后提供一个实现:公共类任务:ITask{public virtual Document Document{get;set;}public IDocument getDocumnet(){return this.Document;}}
.Untested。一个想法可以实现Document:IDocument
,将ITask
定义为ITask{IDocument getDocumnet();}
,最后提供一个实现:公共类任务:ITask{public virtual Document Document{get;set;}public IDocument getDocumnet(){return this.Document;}
。但未经测试。从长远来看,我总觉得我最终会随着实现将接口移出项目,所以我最终开始从现在开始将它们放入自己的程序集中。从长远来看,我总觉得我会随着实现将接口移出项目,所以我最终开始了j我们必须从现在开始把它们放在自己的组件中。