实体框架,抽象类,通用存储库和通用管理器 [英] Entity framework, abstract class, generic repository and generic manager

查看:147
本文介绍了实体框架,抽象类,通用存储库和通用管理器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在项目中,我们使用通用存储库和通用管理器,所以我们不需要在每个库/管理器中重写每个更新/删除等方法。



是他们的样子:

  public interface IBaseRep< T> :IDisposable where T:class,PrivateObject 
{
DbSet< T> DatabaseSet {get;组; }
DbContext Dal {get;组; }

T Find(int?id);
T Find(Expression< Func< T,bool>>谓词);
ICollection< T>选择(表达式< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties =
T Create(T obj);
T更新(T obj);
bool Delete(T obj);
bool Delete(int id);
bool Delete(Expression< Func< T,bool>>谓词);
IQueryable< T> SelectAsQuery(
表达式< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties =
}

public class BaseRep< T> :IBaseRep< T>其中T:class,PrivateObject
{
public DbSet< T> DatabaseSet {get;组; }
public DbContext Dal {get;组;

public EORTCBaseRep(DbContext dal)
{
this.Dal = dal;
this.DatabaseSet = Dal.Set< T>();
}

public virtual T Find(int?id)
{
return this.DatabaseSet.Find(id);
}

public virtual T Find(Expression< Func< T,bool>>谓词)
{
return Select(predicate).FirstOrDefault();
}

public virtual ICollection< T>选择(
表达式< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties = $ b {
return SelectAsQuery(predicate,orderBy,includeProperties).ToList();
}

public virtual IQueryable< T> SelectAsQuery(
Expression< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties = $ b {
IQueryable< T> query = this.DatabaseSet;

if(predicate!= null)
query = query.Where(predicate);

foreach(var includeProperty in includeProperties.Split(new char [] {','},StringSplitOptions.RemoveEmptyEntries))
query = query.Include(includeProperty);

if(orderBy!= null)
query = query.OrderBy(orderBy);

返回查询;
}

public virtual T Create(T obj)
{
this.Dal.Entry< T>(obj).State = EntityState.Added;
this.Dal.SaveChanges();
return obj;
}

public virtual T Update(T obj)
{
this.Dal.Entry< T>(obj).State = EntityState.Modified;
this.Dal.SaveChanges();
return obj;
}

public virtual bool Delete(T obj)
{
if(obj is ILogicallyDeletable)
{
this.Dal.Entry< ; T>(obj).State = EntityState.Modified;
(obj as ILogicallyDeletable).IsDeleted = true;
}
else
{
this.Dal.Entry< T>(obj).State = EntityState.Deleted;
}
return this.Dal.SaveChanges()== 1;
}

public virtual bool Delete(int id)
{
T obj = Find(id);
return Delete(obj);


public virtual bool Delete(Expression< Func< T,bool>> predicate)
{
foreach(Select(predicate)中的T项)
{
删除(item);
}
return this.Dal.SaveChanges()== 1;
}

public virtual void Dispose()
{
this.Dal.Dispose();
}
}

我们的经理看起来像这样:

  public interface IBaseManager< T> :IDisposable where T:class,PrivateObject 
{
T Find(int?id);
T Find(Expression< Func< T,bool>>谓词);
ICollection< T>选择(表达式< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties =
T Create(T obj);
T更新(T obj);
bool Delete(T obj);
bool Delete(int id);
bool Delete(Expression< Func< T,bool>>谓词);
IQueryable< T> SelectAsQuery(
表达式< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties =
}

public class BaseManager< T> :IBaseManager< T>其中T:class,PrivateObject
{
protected IBaseRep< T>库;

public virtual T Find(int?id)
{
return this.Repository.Find(id);
}

public virtual T Find(Expression< Func< T,bool>>谓词)
{
return this.Repository.Find(predicate);
}

public virtual ICollection< T>选择(
表达式< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties = $ b {
return this.Repository.Select(predicate,orderBy,includeProperties);
}

public virtual IQueryable< T> SelectAsQuery(
Expression< Func< T,bool>> predicate = null,
表达式< Func< T,string>> orderBy = null,
string includeProperties = $ b {
return this.Repository.SelectAsQuery(predicate,orderBy,includeProperties);
}

public virtual T Create(T obj)
{
return this.Repository.Create(obj);
}

public virtual T Update(T obj)
{
return this.Repository.Update(obj);
}

public virtual bool Delete(T obj)
{
return this.Repository.Delete(obj);
}

public virtual bool Delete(int id)
{
return this.Repository.Delete(id);
}

public virtual bool Delete(Expression< Func< T,bool>>谓词)
{
return this.Repository.Delete(predicate);
}

public virtual void Dispose()
{
if(this.Repository!= null)
this.Repository.Dispose();
}
}

这样做很好。



但是,我们现在需要为多个实体类型使用相同的数据库表:

  public abstract class AbstractSite:PrivateObject,IActivable,ILogicallyDeletable 
{
public int Id {get;组; }
}

public class EthicCommittee:AbstractSite
{
public int Number {get;组; }
}

public class网站:AbstractSite
{
public string Name {get;组;
}

这是我们如何使用通用管理器:

  public class AbstractSiteManager:BaseManager< AbstractSite> 
{
public AbstractSiteManager(PrismaDAL prismaDAL = null)
{
this.Repository = new AbstractSiteRep(prismaDAL);
}
}

以及我们如何使用通用存储库:

  public class AbstractSiteRep:PrismaBaseRep< AbstractSite> 
{
public AbstractSiteRep(PrismaDAL prismaDAL = null)
:base(prismaDAL)
{}
}

public class PrismaBaseRep< T& ; :BaseRep< T>其中T:class,PrivateObject
{
public PrismaBaseRep(PrismaDAL prismaDAL = null):base((prismaDAL == null)?new PrismaDAL():prismaDAL)
{}
但是现在,我们要使用具体的类型,而不是抽象类型(AbstractSite =抽象;网站=具体,招聘意见=具体...),而不用通用的仓库/经理。所以我们会有X通用存储库(其中X:具体类型的数量)。他们都指向同一个DB表。
这将允许我们避免一个演员,并允许我们限制使用一个经理/存储库来操作的类型。



你们有没有想法如何实现这一点?

解决方案

已解决
我的错误。 >

这个工作正常,因为@Mike C说。



我只是不知道EF能找到正确的表如果我引用了一个具体的对象类型而不是抽象(在TPH中)。


In a project, we use generic repository and generic manager so we don't need to rewrite every update / delete etc method in every repository / manager.

Here is how they looks :

public interface IBaseRep<T> : IDisposable where T : class, PrivateObject
{
    DbSet<T> DatabaseSet { get; set; }
    DbContext Dal { get; set; }

    T Find(int? id);
    T Find(Expression<Func<T, bool>> predicate);
    ICollection<T> Select(Expression<Func<T, bool>> predicate = null,
        Expression<Func<T, string>> orderBy = null,
        string includeProperties = "");
    T Create(T obj);
    T Update(T obj);
    bool Delete(T obj);
    bool Delete(int id);
    bool Delete(Expression<Func<T, bool>> predicate);
    IQueryable<T> SelectAsQuery(
        Expression<Func<T, bool>> predicate = null, 
        Expression<Func<T, string>> orderBy = null, 
        string includeProperties = "");
}

public class BaseRep<T> : IBaseRep<T> where T : class, PrivateObject
{
    public DbSet<T> DatabaseSet { get; set; }
    public DbContext Dal { get; set; }

    public EORTCBaseRep(DbContext dal)
    {
        this.Dal = dal;
        this.DatabaseSet = Dal.Set<T>();
    }

    public virtual T Find(int? id)
    {
        return this.DatabaseSet.Find(id);
    }

    public virtual T Find(Expression<Func<T, bool>> predicate)
    {
        return Select(predicate).FirstOrDefault();
    }

    public virtual ICollection<T> Select(
        Expression<Func<T, bool>> predicate = null,
        Expression<Func<T, string>> orderBy = null,
        string includeProperties = "")
    {
        return SelectAsQuery(predicate, orderBy, includeProperties).ToList();
    }

    public virtual IQueryable<T> SelectAsQuery(
       Expression<Func<T, bool>> predicate = null,
       Expression<Func<T, string>> orderBy = null,
       string includeProperties = "")
    {
        IQueryable<T> query = this.DatabaseSet;

        if (predicate != null)
            query = query.Where(predicate);

        foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            query = query.Include(includeProperty);

        if (orderBy != null)
            query = query.OrderBy(orderBy);

        return query;
    }

    public virtual T Create(T obj)
    {
        this.Dal.Entry<T>(obj).State = EntityState.Added;
        this.Dal.SaveChanges();
        return obj;
    }

    public virtual T Update(T obj)
    {
        this.Dal.Entry<T>(obj).State = EntityState.Modified;
        this.Dal.SaveChanges();
        return obj;
    }

    public virtual bool Delete(T obj)
    {
        if (obj is ILogicallyDeletable)
        {
            this.Dal.Entry<T>(obj).State = EntityState.Modified;
            (obj as ILogicallyDeletable).IsDeleted = true;
        }
        else
        {
            this.Dal.Entry<T>(obj).State = EntityState.Deleted;
        }
        return this.Dal.SaveChanges() == 1;
    }

    public virtual bool Delete(int id)
    {
        T obj = Find(id);
        return Delete(obj);
    }

    public virtual bool Delete(Expression<Func<T, bool>> predicate)
    {
        foreach (T item in Select(predicate))
        {
            Delete(item);
        }
        return this.Dal.SaveChanges() == 1;
    }

    public virtual void Dispose()
    {
        this.Dal.Dispose();
    }
}

Our managers looks like this :

public interface IBaseManager<T> : IDisposable where T : class, PrivateObject
{
    T Find(int? id);
    T Find(Expression<Func<T, bool>> predicate);
    ICollection<T> Select(Expression<Func<T, bool>> predicate = null,
        Expression<Func<T, string>> orderBy = null,
        string includeProperties = "");
    T Create(T obj);
    T Update(T obj);
    bool Delete(T obj);
    bool Delete(int id);
    bool Delete(Expression<Func<T, bool>> predicate);
    IQueryable<T> SelectAsQuery(
        Expression<Func<T, bool>> predicate = null,
        Expression<Func<T, string>> orderBy = null,
        string includeProperties = "");
}

public class BaseManager<T> : IBaseManager<T> where T : class, PrivateObject
{
    protected IBaseRep<T> Repository;

    public virtual T Find(int? id)
    {
        return this.Repository.Find(id);
    }

    public virtual T Find(Expression<Func<T, bool>> predicate)
    {
        return this.Repository.Find(predicate);
    }

    public virtual ICollection<T> Select(
        Expression<Func<T, bool>> predicate = null,
        Expression<Func<T, string>> orderBy = null,
        string includeProperties = "")
    {
        return this.Repository.Select(predicate, orderBy, includeProperties);
    }

    public virtual IQueryable<T> SelectAsQuery(
        Expression<Func<T, bool>> predicate = null,
        Expression<Func<T, string>> orderBy = null,
        string includeProperties = "")
    {
        return this.Repository.SelectAsQuery(predicate, orderBy, includeProperties);
    }

    public virtual T Create(T obj)
    {
        return this.Repository.Create(obj);
    }

    public virtual T Update(T obj)
    {
        return this.Repository.Update(obj);
    }

    public virtual bool Delete(T obj)
    {
        return this.Repository.Delete(obj);
    }

    public virtual bool Delete(int id)
    {
        return this.Repository.Delete(id);
    }

    public virtual bool Delete(Expression<Func<T, bool>> predicate)
    {
        return this.Repository.Delete(predicate);
    }

    public virtual void Dispose()
    {
        if (this.Repository != null)
            this.Repository.Dispose();
    }
}

This works well.

But, we now need to use the same DB table for multiple entity type :

public abstract class AbstractSite : PrivateObject, IActivable, ILogicallyDeletable
{
    public int Id { get; set; }
}

public class EthicCommittee : AbstractSite
{
    public int Number { get; set; }
}

public class Site : AbstractSite
{
    public string Name { get; set; }
}

This is how we use the generic managers :

public class AbstractSiteManager : BaseManager<AbstractSite>
{
    public AbstractSiteManager (PrismaDAL prismaDAL = null)
    {
        this.Repository = new AbstractSiteRep(prismaDAL);
    }
}

and how we use the generic repositories :

public class AbstractSiteRep : PrismaBaseRep<AbstractSite>
{
    public AbstractSiteRep (PrismaDAL prismaDAL = null)
        : base(prismaDAL)
    {}
}

public class PrismaBaseRep<T> : BaseRep<T> where T : class, PrivateObject
{
    public PrismaBaseRep(PrismaDAL prismaDAL = null) : base((prismaDAL == null) ? new PrismaDAL() : prismaDAL)
    { }
}

But now, we would like to use the concrete types and not the abstract type anymore (AbstractSite = abstract; Site = concrete, RecruitingInstitution = concrete...) without touching the generic repository / manager. So we would have X generic repository (where X : number of concrete types). All of them pointing to the same DB table. This would allow us to avoid a cast and allow us to restrict which type we can manipulate using one manager / repository.

Do you, guys, have any idea how i could accomplish this ?

解决方案

Resolved My mistake.

This works fine as @Mike C said.

I just didn't know that EF was able to find the correct table if i was referencing a concrete object type instead of the abstract (in TPH).

这篇关于实体框架,抽象类,通用存储库和通用管理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆