什么是IRepository,它的用途是什么?

时间:2022-07-08 16:00:54

What is a IRepository? Why is it used, brief and simple examples won't hurt.

什么是IRepository ?为什么要使用它,简短的例子不会有什么坏处。

4 个解决方案

#1


39  

MVC promotes separation of concerns, but that doesn't stop at the M V C level.

MVC促进了关注点的分离,但这并不仅限于MVC级别。

Data Access is a concern in itself. It should be done in the M bit of MVC, ie the model. How you structure your model is up to you, but people usually follow tried and tested patterns (why reinvent the wheel?). The Repository Pattern is the current standard. Don't expect a simple formula, however, because the variations are as many as there are developers, almost.

数据访问本身就是一个问题。它应该在MVC的M位(即模型)中完成。你如何构建你的模型取决于你,但是人们通常遵循已经尝试过和测试过的模式(为什么要重新发明*呢?)存储库模式是当前的标准。但是,不要期望有一个简单的公式,因为变化几乎和开发人员一样多。

IRepository is just an interface that you create (it is not part of MVC or ASP.NET or .NET). It allows you to "decouple" your repositories from real implementations. Decoupling is good because it means your code...:

IRepository是您创建的接口(它不是MVC或ASP的一部分)。净或. NET)。它允许您将存储库与实际实现“分离”。解耦是好的,因为它意味着您的代码…

  1. Your code is much more reusable. This is just plain good.
  2. 您的代码更加可重用。这很好。
  3. Your code can use Inversion of Control (or Dependency Injection). This is good to keep your concerns well separated. It is especially good because this allows Unit Testing...
  4. 您的代码可以使用控制反转(或依赖注入)。这是很好的保持你的关注点分开。它特别好,因为它允许单元测试…
  5. Your code can be Unit Tested. This is especially good in large projects with complex algorithms. It is good everywhere because it increases your understanding of the technologies you are working with and the domains you are trying to model in software.
  6. 您的代码可以进行单元测试。这在具有复杂算法的大型项目中尤其有用。它在任何地方都是好的,因为它增加了您对正在使用的技术的理解,以及您试图在软件中建模的领域。
  7. Your code becomes built around best practices, following a common pattern. This is good because it makes maintenance much easier.
  8. 您的代码围绕最佳实践构建,遵循一个公共模式。这很好,因为它使维护更加容易。

So, having sold you decoupling, the answer to your question is that IRepository is an interface that you create and that you make your Repositories inherit from. It gives you a reliable class hierarchy to work with.

所以,在向您介绍了解耦之后,您的问题的答案是IRepository是您创建的接口,并且您使您的存储库继承自该接口。它为您提供了一个可靠的类层次结构。

I generally use a generic IRepository. Ie:

我通常使用一个通用的IRepository。即:

IRepository

IRepository

Where Tentity is, well, an entity. The code I use is:

其中,贞操是一个实体。我使用的代码是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wingspan.Web.Mvc
{
    public interface IRepository<TEntity> where TEntity : class
    {
        List<TEntity> FetchAll();
        IQueryable<TEntity> Query {get;}
        void Add(TEntity entity);
        void Delete(TEntity entity);
        void Save();
    }
}

A concrete implementation of this interface would be:

这个接口的具体实施办法是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

using Wingspan.Web.Mvc;

namespace ES.eLearning.Domain
{
    public class SqlRepository<T> : IRepository<T> where T : class
    {
        DataContext db;
        public SqlRepository(DataContext db)
        {
            this.db = db;
        }

        #region IRepository<T> Members

        public IQueryable<T> Query
        {
            get { return db.GetTable<T>(); }
        }

        public List<T> FetchAll()
        {
            return Query.ToList();
        }

        public void Add(T entity)
        {
            db.GetTable<T>().InsertOnSubmit(entity);
        }

        public void Delete(T entity)
        {
            db.GetTable<T>().DeleteOnSubmit(entity);
        }

        public void Save()
        {
            db.SubmitChanges();
        }

        #endregion
    }
}

This allows me to write:

这让我可以写下:

SqlRepository<UserCourse> UserCoursesRepository = new SqlRepository<UserCourse>(db);

Where db is a DataContext instance injected into, say, a Service.

其中db是注入到服务中的一个DataContext实例。

With UserCoursesRepository I can now write methods in my Service class like:

通过UserCoursesRepository,我现在可以在我的服务类中编写方法,比如:

public void DeleteUserCourse(int courseId)
        {
            var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
            UserCoursesRepository.Delete(uc);
            UserCoursesRepository.Save();
        }

And now in my controllers, I can just write:

现在在控制器中,我可以写:

MyService.DeleteUserCourse(5);
MyService.Save();

Ie, the development of your app becomes more of an assembly line that leads up to a VERY simple controller. Every piece of the assembly line can be tested independently of everything else, so bugs are nipped in the bud.

也就是说,你的应用程序的开发更像是一条流水线,这条流水线可以生成一个非常简单的控制器。装配线上的每一件东西都可以独立地进行测试,因此bug就被扼杀在萌芽之中。

If this is a long, unwieldly answer it is because the real answer is:

如果这是一个冗长而笨拙的答案,那是因为真正的答案是:

Buy Steven Sanderson's book Pro ASP.NET MVC 2 Framework and learn to think in MVC.

购买Steven Sanderson的书专业ASP。NET MVC 2框架,学习用MVC思考。

#2


13  

An IRepository is an interface you specify when you want to implement the Repository Pattern. As @Brian Ball stated, it's not part of .NET it is an interface that you create.

IRepository是您在希望实现存储库模式时指定的接口。正如@Brian Ball所说,它不是。net的一部分,而是你创建的一个接口。

Developers using the Repository Pattern widely recommend the use of an interface for the implementation. For example, in the application I am developing right now, I have 5 repositories. 4 specific and 1 generic. Each one inherits from an IRepository which ensures I will not have issues down the road with differences in implementations.

使用存储库模式的开发人员广泛建议为实现使用接口。例如,在我正在开发的应用程序中,我有5个存储库。4个特异性和1个共性。每一个都是从IRepository继承的,IRepository确保我以后不会有实现差异的问题。

As far as code examples, I'll try:

至于代码示例,我将尝试:

interface IRepository<T> where T : class {
    IQueryable<T> Select();
}

Implemented as a generic repository:

作为通用存储库实现:

public class Repository<T> : IRepository<T> where T : class {
    public IQueryable<T> Select() {
        return this.ObjectContext.CreateObjectSet<T>();
    }
}

Implemented as a specialized repository:

作为专用存储库实现:

public class EmployeeRepository : IRepository<Employee> {
    public IQueryable<Employee> Select() {
        return this.ObjectContext.Employees;
    }
}

Both the Repository<T> and EmployeeRepository implement IRepository, however they go about performing the querying slightly differently. The generic repository has to create an object set of T before it can try to do anything.

存储库 和EmployeeRepository都实现了IRepository,但是它们执行查询的方式略有不同。通用存储库必须创建一个T的对象集,然后才能尝试执行任何操作。

Keep in mind that Repository<T> is supposed to be locked to the interface, where as EmployeeRepository can implement more specialized methods to accomplish more complex logic.

请记住,Repository 应该锁定在接口上,因为EmployeeRepository可以实现更专门化的方法来完成更复杂的逻辑。

I hope this helps you a little.

我希望这能对你有所帮助。

#3


2  

A repository is an abstraction which represents any underlying and arbitrary data store as if it were an in memory collection of objects.

存储库是一种抽象,它表示任何底层的和任意的数据存储,就像它是对象的内存集合一样。

This definition is morphed into a more practical form due to common practices and system limitations as a collection of objects in memory which represent some underlying and arbitrary data store, possibly a disconnected one. Under the hood the repository may be linked to a database, a flat file, an in-memory collection of objects, or whatever else you may imagine. The user of a repository doesn't care.

由于常见的实践和系统限制,这个定义变成了一种更实际的形式,它是内存中的对象集合,表示一些底层的和任意的数据存储,可能是一个不连接的数据存储。在基本框架下,存储库可以链接到数据库、平面文件、内存中对象集合,或者您可以想象的任何其他东西。存储库的用户并不关心。

So an IRepository is the interface contract which defines how Api code wishes client code to interact with the repository. This often includes add, update, delete, and get contracts as for example, this very common example of a repository contract:

因此,IRepository就是接口契约,它定义了Api代码希望客户端代码如何与存储库交互。这通常包括添加、更新、删除和获取契约,例如,存储库契约的一个非常常见的示例:

public interface IRepository<TEntity> where TEntity : class
{
    List<TEntity> GetAll();
    void Add(TEntity entity);
    void Delete(TEntity entity);
    void Save();
}

But I prefer to use a different interface for a few reasons.

但出于一些原因,我更喜欢使用不同的接口。

First, you typically wont be using a repository by itself, you will probably be using it with a unit of work pattern, so the repository shouldn't have a Save() method. It might have an Update(T entity) method - but why? The object which you receive from the repository will automatically be updatable/updated just like any other object you would receive from any kind of collection of objects because you have retrieved references to the objects themselves. (For example: if your TEntity is a Person object, and you get person "Chuck", and you change his last name from "Bartowski" to "Carmichael", the repository has presumably already updated said entity. If this seems tenuous in your mind, there is nothing wrong with implementing an Update(T entity) method.)

首先,您通常不会单独使用存储库,您可能会将它与一个工作模式单元一起使用,因此存储库不应该有Save()方法。它可能有一个Update(T实体)方法——但是为什么呢?您从存储库接收的对象将自动可更新/更新,就像您从任何类型的对象集合接收的任何其他对象一样,因为您已经检索到对对象本身的引用。(例如:如果您的TEntity是Person对象,您获得Person“Chuck”,并将其姓从“Bartowski”更改为“Carmichael”,那么存储库可能已经更新了这个实体。如果在您看来这很脆弱,那么实现Update(T entity)方法没有什么错。

Second, most repositories should be able to handle disconnected environments. If your solution does not have this requirement, you can still create an interface that handles disconnected scenarios and simply leave it unimplemented. Now you are ready for the future.

第二,大多数存储库应该能够处理断开连接的环境。如果您的解决方案没有这个需求,您仍然可以创建一个接口来处理断开连接的场景,并将其保留为未实现。现在你已经为未来做好了准备。

At last, our contract makes more sense to the true nature of a repository - a collection of objects in memory which represent some arbitrary data store, possibly a disconnected one.

最后,我们的契约更符合存储库的本质——内存中的对象集合,它表示一些任意的数据存储,可能是一个断开连接的数据存储。

public interface IRepository<TEntity> where TEntity : class
{

    List<TEntity> GetAll();
    List<TEntity> Get(Func<TEntity, bool> where);
    void Insert(TEntity entity);
    void Insert(IEnumerable<TEntity> entities);
    void Remove(TEntity entity);
    void Remove(IEnumerable<TEntity> entities);

    void SyncDisconnected(TEntity entity, bool forDeletion = false);
    void SyncDisconnected(IEnumerable<TEntity> entities, bool forDeletion = false);
}

If you define a base class for all of your entities, let's call it DomainObject, and you give it an Id field, then you can do the following:

如果你为你所有的实体定义一个基类,让我们称它为DomainObject,你给它一个Id字段,然后你可以做以下事情:

public interface IRepository<TEntity> where TEntity : DomainObject
{
    TEntity GetById(object Id);

    List<TEntity> GetAll();
    List<TEntity> Get(Func<TEntity, bool> where);
    void Insert(TEntity entity);
    void Insert(IEnumerable<TEntity> entities);
    void Remove(TEntity entity);
    void Remove(IEnumerable<TEntity> entities);

    void SyncDisconnected(TEntity entity, bool forDeletion = false);
    void SyncDisconnected(IEnumerable<TEntity> entities, bool forDeletion = false);
}

If you don't like the optional parameter forDeletion, you can add a method which allow syncing deleted objects as well:

如果您不喜欢可选参数forDeletion,您可以添加一个同时同步被删除对象的方法:

    void SyncDisconnectedForDeletion(TEntity entity);

The reason you need to do this is because in most cases, syncing disconnected objects for deletion is incompatible with syncing disconnected objects for addition or modification. (Try it. You will see for yourself the requirements for deletion against a store vary wildly from that of addition or modification). Hence, the interface should define a contract so the implementation can discern between the two.

之所以需要这样做,是因为在大多数情况下,为删除而同步断开连接的对象与为添加或修改而同步断开连接的对象是不兼容的。(试一试。您将看到对商店的删除要求与添加或修改的要求有很大的不同)。因此,接口应该定义一个契约,以便实现能够区分两者。

You can implement this interface against ANY repository of ANY underlying data store, connected or disconnected, including other abstractions to underlying data stores such as Entity Framework.

您可以针对任何底层数据存储、连接或断开的存储库实现此接口,包括对实体框架等底层数据存储的其他抽象。

#4


2  

IRepository is not a defined type in the .Net framework. Usually when you see an interface named that, the program uses the Repository Pattern ( https://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx ). Generally when people use this pattern, they will create an interface that all the repositories adhere to. There are many benefits to doing this. Some of the benefits are code de-copupling, and unit testing.

IRepository在。net框架中不是定义的类型。通常当您看到一个命名为它的接口时,程序使用存储库模式(https://web.archive.org/web/201201503184244/http:通常,当人们使用此模式时,他们将创建一个所有存储库都遵循的接口。这样做有很多好处。一些好处是代码去耦合和单元测试。

It is also common for this to be done so it can be taken advantage of with IoC ( http://en.wikipedia.org/wiki/Inversion_of_control ).

使用IoC (http://en.wikipedia.org/wiki/Inversion_of_control)也很常见。

#1


39  

MVC promotes separation of concerns, but that doesn't stop at the M V C level.

MVC促进了关注点的分离,但这并不仅限于MVC级别。

Data Access is a concern in itself. It should be done in the M bit of MVC, ie the model. How you structure your model is up to you, but people usually follow tried and tested patterns (why reinvent the wheel?). The Repository Pattern is the current standard. Don't expect a simple formula, however, because the variations are as many as there are developers, almost.

数据访问本身就是一个问题。它应该在MVC的M位(即模型)中完成。你如何构建你的模型取决于你,但是人们通常遵循已经尝试过和测试过的模式(为什么要重新发明*呢?)存储库模式是当前的标准。但是,不要期望有一个简单的公式,因为变化几乎和开发人员一样多。

IRepository is just an interface that you create (it is not part of MVC or ASP.NET or .NET). It allows you to "decouple" your repositories from real implementations. Decoupling is good because it means your code...:

IRepository是您创建的接口(它不是MVC或ASP的一部分)。净或. NET)。它允许您将存储库与实际实现“分离”。解耦是好的,因为它意味着您的代码…

  1. Your code is much more reusable. This is just plain good.
  2. 您的代码更加可重用。这很好。
  3. Your code can use Inversion of Control (or Dependency Injection). This is good to keep your concerns well separated. It is especially good because this allows Unit Testing...
  4. 您的代码可以使用控制反转(或依赖注入)。这是很好的保持你的关注点分开。它特别好,因为它允许单元测试…
  5. Your code can be Unit Tested. This is especially good in large projects with complex algorithms. It is good everywhere because it increases your understanding of the technologies you are working with and the domains you are trying to model in software.
  6. 您的代码可以进行单元测试。这在具有复杂算法的大型项目中尤其有用。它在任何地方都是好的,因为它增加了您对正在使用的技术的理解,以及您试图在软件中建模的领域。
  7. Your code becomes built around best practices, following a common pattern. This is good because it makes maintenance much easier.
  8. 您的代码围绕最佳实践构建,遵循一个公共模式。这很好,因为它使维护更加容易。

So, having sold you decoupling, the answer to your question is that IRepository is an interface that you create and that you make your Repositories inherit from. It gives you a reliable class hierarchy to work with.

所以,在向您介绍了解耦之后,您的问题的答案是IRepository是您创建的接口,并且您使您的存储库继承自该接口。它为您提供了一个可靠的类层次结构。

I generally use a generic IRepository. Ie:

我通常使用一个通用的IRepository。即:

IRepository

IRepository

Where Tentity is, well, an entity. The code I use is:

其中,贞操是一个实体。我使用的代码是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wingspan.Web.Mvc
{
    public interface IRepository<TEntity> where TEntity : class
    {
        List<TEntity> FetchAll();
        IQueryable<TEntity> Query {get;}
        void Add(TEntity entity);
        void Delete(TEntity entity);
        void Save();
    }
}

A concrete implementation of this interface would be:

这个接口的具体实施办法是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

using Wingspan.Web.Mvc;

namespace ES.eLearning.Domain
{
    public class SqlRepository<T> : IRepository<T> where T : class
    {
        DataContext db;
        public SqlRepository(DataContext db)
        {
            this.db = db;
        }

        #region IRepository<T> Members

        public IQueryable<T> Query
        {
            get { return db.GetTable<T>(); }
        }

        public List<T> FetchAll()
        {
            return Query.ToList();
        }

        public void Add(T entity)
        {
            db.GetTable<T>().InsertOnSubmit(entity);
        }

        public void Delete(T entity)
        {
            db.GetTable<T>().DeleteOnSubmit(entity);
        }

        public void Save()
        {
            db.SubmitChanges();
        }

        #endregion
    }
}

This allows me to write:

这让我可以写下:

SqlRepository<UserCourse> UserCoursesRepository = new SqlRepository<UserCourse>(db);

Where db is a DataContext instance injected into, say, a Service.

其中db是注入到服务中的一个DataContext实例。

With UserCoursesRepository I can now write methods in my Service class like:

通过UserCoursesRepository,我现在可以在我的服务类中编写方法,比如:

public void DeleteUserCourse(int courseId)
        {
            var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
            UserCoursesRepository.Delete(uc);
            UserCoursesRepository.Save();
        }

And now in my controllers, I can just write:

现在在控制器中,我可以写:

MyService.DeleteUserCourse(5);
MyService.Save();

Ie, the development of your app becomes more of an assembly line that leads up to a VERY simple controller. Every piece of the assembly line can be tested independently of everything else, so bugs are nipped in the bud.

也就是说,你的应用程序的开发更像是一条流水线,这条流水线可以生成一个非常简单的控制器。装配线上的每一件东西都可以独立地进行测试,因此bug就被扼杀在萌芽之中。

If this is a long, unwieldly answer it is because the real answer is:

如果这是一个冗长而笨拙的答案,那是因为真正的答案是:

Buy Steven Sanderson's book Pro ASP.NET MVC 2 Framework and learn to think in MVC.

购买Steven Sanderson的书专业ASP。NET MVC 2框架,学习用MVC思考。

#2


13  

An IRepository is an interface you specify when you want to implement the Repository Pattern. As @Brian Ball stated, it's not part of .NET it is an interface that you create.

IRepository是您在希望实现存储库模式时指定的接口。正如@Brian Ball所说,它不是。net的一部分,而是你创建的一个接口。

Developers using the Repository Pattern widely recommend the use of an interface for the implementation. For example, in the application I am developing right now, I have 5 repositories. 4 specific and 1 generic. Each one inherits from an IRepository which ensures I will not have issues down the road with differences in implementations.

使用存储库模式的开发人员广泛建议为实现使用接口。例如,在我正在开发的应用程序中,我有5个存储库。4个特异性和1个共性。每一个都是从IRepository继承的,IRepository确保我以后不会有实现差异的问题。

As far as code examples, I'll try:

至于代码示例,我将尝试:

interface IRepository<T> where T : class {
    IQueryable<T> Select();
}

Implemented as a generic repository:

作为通用存储库实现:

public class Repository<T> : IRepository<T> where T : class {
    public IQueryable<T> Select() {
        return this.ObjectContext.CreateObjectSet<T>();
    }
}

Implemented as a specialized repository:

作为专用存储库实现:

public class EmployeeRepository : IRepository<Employee> {
    public IQueryable<Employee> Select() {
        return this.ObjectContext.Employees;
    }
}

Both the Repository<T> and EmployeeRepository implement IRepository, however they go about performing the querying slightly differently. The generic repository has to create an object set of T before it can try to do anything.

存储库 和EmployeeRepository都实现了IRepository,但是它们执行查询的方式略有不同。通用存储库必须创建一个T的对象集,然后才能尝试执行任何操作。

Keep in mind that Repository<T> is supposed to be locked to the interface, where as EmployeeRepository can implement more specialized methods to accomplish more complex logic.

请记住,Repository 应该锁定在接口上,因为EmployeeRepository可以实现更专门化的方法来完成更复杂的逻辑。

I hope this helps you a little.

我希望这能对你有所帮助。

#3


2  

A repository is an abstraction which represents any underlying and arbitrary data store as if it were an in memory collection of objects.

存储库是一种抽象,它表示任何底层的和任意的数据存储,就像它是对象的内存集合一样。

This definition is morphed into a more practical form due to common practices and system limitations as a collection of objects in memory which represent some underlying and arbitrary data store, possibly a disconnected one. Under the hood the repository may be linked to a database, a flat file, an in-memory collection of objects, or whatever else you may imagine. The user of a repository doesn't care.

由于常见的实践和系统限制,这个定义变成了一种更实际的形式,它是内存中的对象集合,表示一些底层的和任意的数据存储,可能是一个不连接的数据存储。在基本框架下,存储库可以链接到数据库、平面文件、内存中对象集合,或者您可以想象的任何其他东西。存储库的用户并不关心。

So an IRepository is the interface contract which defines how Api code wishes client code to interact with the repository. This often includes add, update, delete, and get contracts as for example, this very common example of a repository contract:

因此,IRepository就是接口契约,它定义了Api代码希望客户端代码如何与存储库交互。这通常包括添加、更新、删除和获取契约,例如,存储库契约的一个非常常见的示例:

public interface IRepository<TEntity> where TEntity : class
{
    List<TEntity> GetAll();
    void Add(TEntity entity);
    void Delete(TEntity entity);
    void Save();
}

But I prefer to use a different interface for a few reasons.

但出于一些原因,我更喜欢使用不同的接口。

First, you typically wont be using a repository by itself, you will probably be using it with a unit of work pattern, so the repository shouldn't have a Save() method. It might have an Update(T entity) method - but why? The object which you receive from the repository will automatically be updatable/updated just like any other object you would receive from any kind of collection of objects because you have retrieved references to the objects themselves. (For example: if your TEntity is a Person object, and you get person "Chuck", and you change his last name from "Bartowski" to "Carmichael", the repository has presumably already updated said entity. If this seems tenuous in your mind, there is nothing wrong with implementing an Update(T entity) method.)

首先,您通常不会单独使用存储库,您可能会将它与一个工作模式单元一起使用,因此存储库不应该有Save()方法。它可能有一个Update(T实体)方法——但是为什么呢?您从存储库接收的对象将自动可更新/更新,就像您从任何类型的对象集合接收的任何其他对象一样,因为您已经检索到对对象本身的引用。(例如:如果您的TEntity是Person对象,您获得Person“Chuck”,并将其姓从“Bartowski”更改为“Carmichael”,那么存储库可能已经更新了这个实体。如果在您看来这很脆弱,那么实现Update(T entity)方法没有什么错。

Second, most repositories should be able to handle disconnected environments. If your solution does not have this requirement, you can still create an interface that handles disconnected scenarios and simply leave it unimplemented. Now you are ready for the future.

第二,大多数存储库应该能够处理断开连接的环境。如果您的解决方案没有这个需求,您仍然可以创建一个接口来处理断开连接的场景,并将其保留为未实现。现在你已经为未来做好了准备。

At last, our contract makes more sense to the true nature of a repository - a collection of objects in memory which represent some arbitrary data store, possibly a disconnected one.

最后,我们的契约更符合存储库的本质——内存中的对象集合,它表示一些任意的数据存储,可能是一个断开连接的数据存储。

public interface IRepository<TEntity> where TEntity : class
{

    List<TEntity> GetAll();
    List<TEntity> Get(Func<TEntity, bool> where);
    void Insert(TEntity entity);
    void Insert(IEnumerable<TEntity> entities);
    void Remove(TEntity entity);
    void Remove(IEnumerable<TEntity> entities);

    void SyncDisconnected(TEntity entity, bool forDeletion = false);
    void SyncDisconnected(IEnumerable<TEntity> entities, bool forDeletion = false);
}

If you define a base class for all of your entities, let's call it DomainObject, and you give it an Id field, then you can do the following:

如果你为你所有的实体定义一个基类,让我们称它为DomainObject,你给它一个Id字段,然后你可以做以下事情:

public interface IRepository<TEntity> where TEntity : DomainObject
{
    TEntity GetById(object Id);

    List<TEntity> GetAll();
    List<TEntity> Get(Func<TEntity, bool> where);
    void Insert(TEntity entity);
    void Insert(IEnumerable<TEntity> entities);
    void Remove(TEntity entity);
    void Remove(IEnumerable<TEntity> entities);

    void SyncDisconnected(TEntity entity, bool forDeletion = false);
    void SyncDisconnected(IEnumerable<TEntity> entities, bool forDeletion = false);
}

If you don't like the optional parameter forDeletion, you can add a method which allow syncing deleted objects as well:

如果您不喜欢可选参数forDeletion,您可以添加一个同时同步被删除对象的方法:

    void SyncDisconnectedForDeletion(TEntity entity);

The reason you need to do this is because in most cases, syncing disconnected objects for deletion is incompatible with syncing disconnected objects for addition or modification. (Try it. You will see for yourself the requirements for deletion against a store vary wildly from that of addition or modification). Hence, the interface should define a contract so the implementation can discern between the two.

之所以需要这样做,是因为在大多数情况下,为删除而同步断开连接的对象与为添加或修改而同步断开连接的对象是不兼容的。(试一试。您将看到对商店的删除要求与添加或修改的要求有很大的不同)。因此,接口应该定义一个契约,以便实现能够区分两者。

You can implement this interface against ANY repository of ANY underlying data store, connected or disconnected, including other abstractions to underlying data stores such as Entity Framework.

您可以针对任何底层数据存储、连接或断开的存储库实现此接口,包括对实体框架等底层数据存储的其他抽象。

#4


2  

IRepository is not a defined type in the .Net framework. Usually when you see an interface named that, the program uses the Repository Pattern ( https://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx ). Generally when people use this pattern, they will create an interface that all the repositories adhere to. There are many benefits to doing this. Some of the benefits are code de-copupling, and unit testing.

IRepository在。net框架中不是定义的类型。通常当您看到一个命名为它的接口时,程序使用存储库模式(https://web.archive.org/web/201201503184244/http:通常,当人们使用此模式时,他们将创建一个所有存储库都遵循的接口。这样做有很多好处。一些好处是代码去耦合和单元测试。

It is also common for this to be done so it can be taken advantage of with IoC ( http://en.wikipedia.org/wiki/Inversion_of_control ).

使用IoC (http://en.wikipedia.org/wiki/Inversion_of_control)也很常见。