我正在创建我的第一个EF 6 Code第一个应用程序。 StackOverflow帮助了我很多问题。然而,信息隐藏仍然困扰着我。
在创建将操纵数据库的POCO实体类之后,我创建了Repository<T>
类(和接口),隐藏了使用DbSet<T>
的事实,以及一个UnitOfWork
类。围绕DbContext
和存储库的包装器。
下面我将介绍工作单元/存储库模式的摘要。最终会导致这个问题:
DbSet
使用的原始实体对象会暴露出比我想要公开的更多成员,例如外键。我应该公开用于创建DbSet
对象的原始实体类,还是应该包含用于CRUD数据库中实体的其他类/接口。
为了描述问题,我将常用的示例与博客和帖子一起使用,例如:MSDN Code First to a new database
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
在设计方面:博客有零个或多个帖子。博客和帖子之间存在一对多的关系。
该框架将创建两个数据库表:一个包含Blogs,另一个包含Posts。每个帖子都有一个外键给它所属的博客。
DbContext
:
public class BlogContext: DbContext
{
public virtual DbSet<Blog> Blogs {get; set;}
public virtual DbSet<Post> Posts {get; set;}
}
IRepository
旨在隐藏使用DbSet
:
public interface IRepository<T> where T: class ...
{
T GetById(int id);
void Insert(T entity);
void Update(T entity);
void Remove(T entity);
...
}
public interface IUnitOfWork : System.IDisposable
{
IRepository<Blog> Blogs {get;}
IRepository<Post> Posts {get;}
void Commit();
}
到目前为止,这么好,相当简单,并根据几个关于这个主题的帖子。帮助了我很多的是Implementing a Data Access Layer with Entity Framework 6.1
问题是通常模式的描述在此处停止。为了能够使用它,我需要一个BlogControl类,它代表我的客户端的接口。该界面(a.o.)具有为博主添加博客和帖子的功能。我的第一枪就是:
public interface IBlogControl
{
void CreateBlog(Blog blog); // create a Blog without Posts
void AddPost(Post post); // create a post for the blog with Post.BlogId
...
}
这些函数将创建一个工作单元,访问存储库以更改序列化数据并提交以保存所有更改。
困扰我这是因为我将Blog
和Post
暴露给了外部世界,这允许不受欢迎的使用。
例如,人们可以创建一个附有多个帖子的博客,或者添加一个与BlogId
不对应的博客的帖子。阻止这种情况的一种方法是不公开Blog
和Post
,但是只显示我想要公开的属性和方法的接口IBlog
和IPost
。 / p>
然而,这样做的缺点是人们可以设计自己的博客/帖子类来实现IBlog
/ IPost
,这样就必须将所有数据复制到我自己隐藏的Blog
/ {{ 1}}对象。
另一种方法是在更改存储库之前检查是否满足所有先决条件。
然而,这些方法效率很低。
所以问题:在使用工作单元/存储库模式时,它是否意味着公开构成我的数据库的原始实体类?我应该只将接口暴露给我想要公开的属性吗?或者我应该提供不公开原始实体类的函数吗?