通用存储库模式 IEntity 属性 区分大小写

Generic Repository Pattern IEntity property case sensitivity

我在我的应用程序中使用通用存储库模式。我正在尝试这个 post http://www.remondo.net/repository-pattern-example-csharp/。问题是,数据库代码生成工具(代码优先来自现有数据库)生成以下模型:

[Table("TableName1")]
public partial class TableName1 : IEntity
{
    public int ID { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    ::::::::
}

[Table("TableName2")]
public partial class TableName2 : IEntity
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    ::::::::
}

而且我刚刚在上述数据库模型中应用了 IEntity,但是 TableName2 class 中存在问题,因为 IEntity 接口具有 'ID' 属性 而不是 'Id'。这是一个

public interface IEntity
{
    int ID { get; }
}

那么如何在不查看大小写的情况下将此 IEntity 转换为接受属性?如果我不想为每个 table?

创建单独的独立新模型,我需要最简单的解决方案

如果您使用代码优先方法,Entity Framework 会在生成 table 时自动将您的实体名称复数化,因此让我们先为您的问题添加一些上下文并删除所有抽象,假设我们正在创建一个用户存储库,实体框架将自动生成一个 Users table.

public partial class User : IEntity
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Name { get; set; }
}

public partial class BlogPost : IEntity
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Title { get; set; }
}

public interface IEntity
{
    int Id { get; }
}

没有办法绕过大小写规则,这是一个规则,尽管我们喜欢做牛仔,但你写的东西甚至不能编译,因为 interface合同。如果 class 实施 合同 ,它必须实施 合同 概述的所有内容; 属性 Id 至少有一个 getter.

我查看了您提供的 link,它没有告诉您应该如何正确实施 IRepository,您的每个实体都应该有自己的存储库,我会修改那个界面,让它变成这样:

public interface IRepository<T> where T : class, IEntity
{
    void Insert(T entity);
    void Delete(T entity);
    IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
    IQueryable<T> GetAll();
    T GetById(int id);
}

我们在这里所做的是,我们已经说过 IRepository 将与任何实现 IRepository 接受实现 IEntity 契约的 type parameter 的存储库一起工作。

public class UserRepository<User> : IRepository<User>
{ 
    protected Table<User> DataTable;

    public Repository(DataContext dataContext)
    {
        DataTable = dataContext.GetTable<User>();
    }

    #region IRepository<T> Members

    public void Insert(User entity)
    {
        DataTable.InsertOnSubmit(entity);
    }

    public void Delete(User entity)
    {
        DataTable.DeleteOnSubmit(entity);
    }

    public IQueryable<User> SearchFor(Expression<Func<User, bool>> predicate)
    {
        return DataTable.Where(predicate);
    }

    public IQueryable<User> GetAll()
    {
        return DataTable;
    }

    public User GetById(int id)
    {
        // Sidenote: the == operator throws NotSupported Exception!
        // 'The Mapping of Interface Member is not supported'
        // Use .Equals() instead
        return DataTable.Single(e => e.Id.Equals(id));
    }

    #endregion
}

我使用的方法现在被 Entity Framework 本身克服了,不确定 Entity Framework 的哪个版本。下面的代码显示了 Entity Framework 的通用存储库模式的一个漂亮而干净的实现。这里不需要 IEntity 接口,因为我们使用了 DbSet class.

的方便的 Find 扩展方法

这里是 IRepository:

public interface IRepository<T>
{
    void Insert(T entity);
    void Delete(T entity);
    IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
    IQueryable<T> GetAll();
    T GetById(int id);
}

这是存储库:

public class Repository<T> : IRepository<T> where T : class
{
    protected DbSet<T> DbSet;

    public Repository(DbContext dataContext)
    {
        DbSet = dataContext.Set<T>();
    }

    #region IRepository<T> Members

    public void Insert(T entity)
    {
        DbSet.Add(entity);
    }

    public void Delete(T entity)
    {
        DbSet.Remove(entity);
    }

    public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    public IQueryable<T> GetAll()
    {
        return DbSet;
    }

    public T GetById(int id)
    {
        return DbSet.Find(id);
    }

    #endregion
}

保持 Entity Framework Code First 代码不变。现在,我们准备在应用程序中使用这个通用存储库,方法如下:

using (var dataContext = new UserBaseContext())
{
    var userRepository = new Repository<Users>(dataContext);

    Users user = userRepository
        .SearchFor(c => c.Name.StartsWith("A"))
        .Single();

    //do other stuff

}

而且这不会抱怨外壳等问题,很高兴我有了第一个可用的通用存储库:)