您需要退一步思考存储库应该做什么。存储库用于检索记录、添加记录和更新记录。您创建的存储库几乎无法处理第一种情况,处理第二种情况但效率不高,并且根本不处理第三种情况。
大多数通用存储库都有一个类似于
public interface IRepository<T> where T : class
{
IQueryable<T> Get();
void Add(T item);
void Delete(T item);
void CommitChanges();
}
为了检索记录,您不能只使用AsEnumerable()
因为这会将该表的每个数据库记录加载到内存中。如果您只想要用户名为username1
,您不需要下载数据库的每个用户,因为这将对数据库性能造成很大的影响,并且对客户端性能造成很大的影响,但根本没有任何好处。
相反,正如您从我上面发布的界面中看到的,您想要返回一个IQueryable<T>
目的。IQuerable
允许调用存储库的任何类使用 Linq 并向数据库查询添加过滤器,并且一旦 IQueryable 运行,它就完全在数据库上运行,只检索您想要的记录。数据库在排序和过滤数据方面比您的系统要好得多,因此最好在数据库上尽可能多地进行操作。
现在关于插入数据,您有正确的想法,但您不想调用SaveChanges()
立即地。原因是最好打电话Savechanges()
在所有数据库操作都已排队之后。例如,如果您想在一个操作中创建一个用户及其个人资料,则不能通过您的方法,因为每个Insert
调用将导致数据被插入到数据库中。
相反,你想要的是分离出Savechanges()
呼叫进入CommitChanges
方法我上面有。
这也需要处理数据库中的数据更新。为了更改实体的数据,实体框架会跟踪它收到的所有记录并监视它们以查看是否进行了任何更改。但是,您仍然需要告诉实体框架将所有更改的数据发送到数据库。这种情况发生在context.SaveChanges()
称呼。因此,您需要将其作为单独的调用,以便能够实际更新已编辑的数据,而当前的实现无法处理这些数据。
Edit:
Your comment made me realize another issue that I see. One downfall is that you are creating a data context inside of the repository, and this isn't good. You really should have all (or most) of your created repositories sharing the same instance of your data context.
实体框架会跟踪在哪个上下文中跟踪实体,并且如果您尝试用另一个上下文更新一个上下文中的实体,则会出现异常。当您开始编辑彼此相关的实体时,这种情况可能会发生。这也意味着您的SaveChanges()
调用不是事务性的,每个实体都在其自己的事务中更新/添加/删除,这可能会变得混乱。
我在存储库中对此的解决方案是DbContext
被传递到构造函数中的存储库中。