【问题标题】:Repository method to find an entity with a non-Primary Key value用于查找具有非主键值的实体的存储库方法
【发布时间】:2012-11-29 09:25:59
【问题描述】:

所以我不确定标题中的术语是否正确,但我应该能够描述我正在尝试做的事情。

我有一个“GenericRepository”类,我的所有实际存储库类都继承自该类,它包含几个通用方法。该类的代码如下

public class GenericRepository<TEntity> where TEntity : class
{
    internal ReportsDirectoryEntities context;
    internal DbSet<TEntity> dbSet;

    public GenericRepository(ReportsDirectoryEntities context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }

    /////////////////////////////////////////////////////////////////////

    public virtual IEnumerable<TEntity> GetAll()
    {
        return dbSet.ToList();
    }
    public virtual TEntity GetByID(int id)
    {
        return dbSet.Find(id);
    }
    public virtual void Insert(TEntity entity)
    {
        dbSet.Add(entity);
    }
    public virtual void Delete(object id)
    {
        TEntity entityToDelete = dbSet.Find(id);
        Delete(entityToDelete);
    }
    public virtual void Delete(TEntity entityToDelete)
    {
        if (context.Entry(entityToDelete).State == System.Data.EntityState.Detached)
        {
            dbSet.Attach(entityToDelete);
        }
        dbSet.Remove(entityToDelete);
    }
    public virtual void Update(TEntity entityToUpdate)
    {
        dbSet.Attach(entityToUpdate);
        context.Entry(entityToUpdate).State = System.Data.EntityState.Modified;
    }
}

现在一切都很好,我现在要做的是添加一个 GetByName 方法,我可以在其中传入实体的“名称”属性并返回它。

我试过了

    public virtual TEntity GetByName(string name)
    {
        return (from e in context.Set<TEntity>()
                where e.Name == name
                select e).SingleOrDefault();
    } 

但是在 Name 下划线表示“TEntity 不包含名称的定义”等等,这是有道理的。

我可以在单独的存储库中轻松做到这一点,但想知道是否有一种方法可以在通用存储库中做到这一点。

非常感谢任何帮助!

【问题讨论】:

    标签: c# entity-framework repository repository-pattern dbcontext


    【解决方案1】:

    为了清楚地做到这一点,TEntity 需要被限制为具有 Name 属性的类型(或接口)。否则,您将使用反射(或 dynamic 访问 Name 属性),这允许在运行时才被捕获的错误。

    【讨论】:

    • AFAIK 我所有继承自此的实体都有一个 Name 属性,但我从你所说的内容中得到的是,我应该将此方法放入每个单独的存储库中。
    • @BenBlack 你的所有类型是否都具有 Name 属性并不重要,除非它们都继承自某个具有 Name 属性的类型或接口。
    • 要回答您的其他评论,是的,我只需将其放入每个存储库中。复制的代码并不多。
    • 这就是我最终所做的,因为我查看了并非所有实体“名称”属性实际上都命名为“名称”。 edi 只是因为我很好奇,我将如何扩展当前的实现以便我可以做到这一点。我觉得我明白你在说什么,但不确定我明白该怎么做。 (我对此有点新手)。我尝试让 GenericRepository 实现一个具有 Name 属性的接口,但似乎没有这样做。
    【解决方案2】:

    如果您的所有实体类型都具有Name 属性,那么您可以使用Name 属性扩展TEntity 接口。

    否则,您可以使用DbSetSqlQuery()方法以字符串查询为参数。

    【讨论】:

    • 感谢 SqlQuery() 方法,我没见过。自从您回答了我最初的问题以来,我将继续并将其标记为答案。
    【解决方案3】:

    如果您的所有实体都使用 Name 作为属性,您只需创建一个接口并将其用作泛型类的约束。

    界面:

    public interface IStringName
    {
        public string Name { get; set; }
    }
    

    实体:

    public partial class MyEntity : IStringName
    {
        public String Name { get; set; }
        // Additional properties here.
    }
    

    存储库:

    public class GenericRepository<TEntity> where TEntity : class, IStringName
    {
        // Your code here.
    }
    

    如果您的实体之一不使用 Name 属性,您有几个选择。您可以将实体中的适当属性名称更改为 Name,并将其适当地映射到原始存储模型名称。或者,您可以继承原始的通用存储库,例如。

    命名存储库:

    public class NamedRepository<TEntity> : GenericRepository<TEntity>
        where TEntity : class, IStringName
    {
        public NamedRepository(ReportsDirectoryEntities context) : base(context)
        {
        }
    
        public virtual TEntity GetByName(string name)
        {
            return (from e in base.context.Set<TEntity>()
                    where e.Name == name
                    select e).SingleOrDefault();
        }
    }
    

    这种方法允许您在实现了新接口的实体上使用 NamedRepository,并为那些没有实现的实体使用原始 GenericRepository。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多