代码之家  ›  专栏  ›  技术社区  ›  Gup3rSuR4c

实体框架中的LINQ到SQL通用存储库等价物

  •  4
  • Gup3rSuR4c  · 技术社区  · 13 年前

    我正在为我的ORM从LINQ转换到SQL,并更新我的存储库。所有这些都完成了,除了一般的。我好像想不出怎么把我的 Select 方法,从现在的方法到使用EF的方法。以下是当前代码:

    public T Select(int Id)
    {
        MetaDataMember PrimaryKey = this.DataContext.Mapping.GetTable(typeof(T)).RowType.DataMembers.SingleOrDefault(
            d =>
                (d.IsPrimaryKey));
        ParameterExpression Param = Expression.Parameter(typeof(T), "e");
    
        var Query = Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(Param, PrimaryKey.Name), Expression.Constant(Id)), new ParameterExpression[] { Param });
    
        return this.DataContext.GetTable<T>().Single(Query);
    }
    

    我没有写这个,我从别人的博客上抄了下来,到目前为止对我很管用。我真的不知道它的作用,模糊的想法,但我不能把它翻译成英孚。

    所以,我来这里请求你们的帮助,女士们先生们。如果可能的话,我希望有人谁知道英孚可以转换这种说法。如果有其他代码可以完成同样的任务,我愿意接受。

    1 回复  |  直到 13 年前
        1
  •  2
  •   RPM1984    13 年前

    如果我正确理解该方法,它将基于主键返回任何类型T的单个记录。

    我们还有一个通用存储库,但界面如下:

    public interface IRepository<T> where T : class
    {
       void Add(T entity);
       void Remove(T entity);
       void Attach(T entity);
       IQueryable<T> Find();
    }
    

    以及我们的通用存储库实现:

    public class GenericRepository<T> : IRepository<T> where T : class
    {
       public IQueryable<T> Find()
       {
          return _ctx.GetEntitySet<T>(); // EF plularization/reflection smarts
       }
    }
    

    因此,要获得“Post”的等效单记录:

    var postId = 1;
    IRepository<Post> repository = new GenericRepository<Post>(); // done by DI in reality
    repository
       .Find()
       .SingleOrDefault(x => x.PostId == postId); // explicit predicate to grab record
    

    这与原始代码大不相同,因为调用代码指定主键是什么(或标识唯一记录的方法)。

    老实说,尝试基于一个固定的主键值动态地获取一个唯一的记录是非常疯狂的- 如果是复合键呢? 我看不出那代码是怎么工作的。

    很高兴看到其他答案,但我会保持简单。

    如果你想让代码获取基于T的实体集,我可以共享它——但它非常简单。

    如果希望方法获取单个记录,请让调用代码提供谓词/键:

    public T FindSingle(Expression<Func<T,bool>> predicate)
    {
       return _ctx.GetEntitySet<T>.SingleOrDefault(predicate);
    }
    

    然后,如果例如“Post”有一个组合键“PostName”和“PostType”:

    var singlePost = repository.FindSingle(post => post.PostName == "Foo" && post.PostType == "Question");
    

    在您的示例中,存储库正在指示您的模型,使每个实体都有一个列主键。

    您的存储库应该 帮助 你的模型,而不是定义它。

    编辑-代码 GetEntitySet<T> ,按要求

    public IObjectSet<T> GetEntitySet<T>() where T : class
    {
       var entityName = _plularizer.Pluralize(typeof(T).Name);
       string entitySetName = string.Format("{0}.{1}", EntityContainerName, entityName);
       return CreateObjectSet<T>(entitySetName );
    }
    

    很简单,很安全,因为 _plularizer 属于类型 System.Data.Entity.Design.PluralizationService ,它与EF用于创建默认实体集名称的模块相同。

    EntityContainerName 是实体的容器名称。

    你的 _脉冲发生器 实例应该是 静止的 ,并使用完全锁定的单例保持线程安全。

    哦。