Repository模式和继承在.net中 [英] Repository pattern and inheritance in .net

查看:146
本文介绍了Repository模式和继承在.net中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是pretty的新版本库的设计模式,我已经走进了死胡同,而试图实现它,关于继承。

i am pretty new to the repository design pattern and i have reached a dead end while trying to implement it, with regards to inheritance.

我不知道,即使我开始在正确的方向。

I am not sure even if i started in the right direction.

所以基本上我将有一个抽象基类的产品,通过ID和的ImagePath例如,也就有了从这个继承几款产品。

So basically i will have an abstract base class Product, with id and imagePath for instance, and will have several products which inherit from this.

namespace Common
{
    public abstract class Product
    {
        public int Id { get; set; }
        public string ImgPath { get; set; }
    }

    public class Scale : Product
    {
        public int AdditionalProperty { get; set; }
    }
}

现在的库如下:

public class BaseRepository
{
    protected TEstEntities1 _dataContext = new TEstEntities1();

    public BaseRepository()
    {
        _dataContext = new TEstEntities1();
    }
}

public interface IProductRepository 
{
    Common.Product Get(int id);
    void Add(Common.Product p);
    void Update(Common.Product p);
    List<Common.Product> ListAll();
}

public class ProductRepository : BaseRepository, IProductRepository
{
    public Common.Product Get(int id)
    {
        throw new NotImplementedException();
    }

    public void Add(Common.Product p)
    {
        throw new NotImplementedException();
    }

    public void Update(Common.Product p)
    {
        throw new NotImplementedException();
    }

    public List<Common.Product> ListAll()
    {
        throw new NotImplementedException();
    }
}

我的问题是:如何整合有关的业务规模?这似乎是一个坏主意,添加类似添加(Common.Scale S)到IProductRepository。这似乎是一个坏主意,看到添加(Common.Product P)内的哪种类型的产品我尝试添加,然后投给它,然后添加。

My problem is as follows: how do i integrate operations regarding Scale ? It seems a bad idea to add something like Add(Common.Scale s) to the IProductRepository. It seems like a bad idea to see inside the Add(Common.Product p) which type of Product i try to add, then cast to it, then add.

我想,如果我是更彻底地说明这个问题,我想重复尽可能少code地,以某种方式隔离基础产品添加/删除code在产品资料库,并以某种方式把如具体尺度code添加/删除另一个类或方法中。

I guess that if i were to describe this problem more thoroughly, I want to repeat as few code as possible, to somehow isolate base product adding/removing code in the product repository, and somehow put e.g. Scale specific code for adding/removing inside another class, or method.

我的一个更彻底的方法是这样:

A more thorough approach of mine has been this one:

public interface IProductRepository<T> where T : Common.Product
{
    T Get(int id);
    void Add(T p);
    void Delete(T p);
}

public abstract class ProductRepository : BaseRepository
{
    protected void Add(Common.Product p)
    {
        _dataContext.AddToProduct(new Product { Id = p.Id, Image = p.ImgPath });
        _dataContext.AcceptAllChanges();
    }

    protected void Delete(Common.Product p)
    {
        var c = _dataContext.Product.Where(x => x.Id == p.Id).FirstOrDefault();
        _dataContext.DeleteObject(c);
        _dataContext.AcceptAllChanges();
    }

    protected Product Get(int id)
    {
        return _dataContext.Product.Where(x => x.Id == id).FirstOrDefault();
    }
}

public class CantarRepository : ProductRepository, IProductRepository<Common.Scale>
{
    public void Add(Common.Scale p)
    {
        base.Add(p);
        _dataContext.Scale.AddObject
             (new Scale { ProductId = p.Id, AdditionalProperty = p.AdditionalProperty });
        _dataContext.AcceptAllChanges();
    }

    public void Delete(Common.Scale p)
    {
        var c = _dataContext.Scale.Where(x => x.ProductId == p.Id);
        _dataContext.DeleteObject(c);
        _dataContext.AcceptAllChanges();
        base.Delete(p);
    }

    public new Common.Scale Get(int id)
    {
        var p = base.Get(id);
        return new Common.Scale
        {
            Id = p.Id,
            ImgPath = p.Image,
            AdditionalProperty = _dataContext.Scale.Where
               (c => c.ProductId == id).FirstOrDefault().AdditionalProperty
        };
    }
}

很遗憾,这属于短期的原因之一。 因为协方差和逆变,如果我使用工厂模式返回IProductRepository和里面我实例化IProductRepository这是不行的,而IProductRepository不能逆变和协变的同时,和分裂方法分为两个接口似乎有悖常理和麻烦的。

Unfortunatelly this falls short for one reason. If i use a factory pattern to return an IProductRepository and inside it i instantiate with IProductRepository this will not work because of covariance and contravariance, and IProductRepository can't be contravariant and covariant at the same time, and splitting the methods into two interfaces seems counterintuitive and cumbersome.

我怀疑我需要的工厂模式,才能有返回基类的接口,但是我愿意接受建议,在这一点。正如我已经说过,我是有关回购的模式非常的新手。

I suspect i will need the factory pattern in order to have a base class interface returned, but i am open to suggestions on this as well. As i've said, i am very newbie regarding the repo pattern.

我很好奇,什么我做错了,我怎么能解决这个问题,我如何能实现这更好的。

I am curious as to what i am doing wrong, how i can solve this, and how can i implement this better.

感谢。

推荐答案

我不是一般的存储库的忠实粉丝,但看着你的code后,我认为你应该使用它:

I'm not a big fan of generic repository but after looking at your code I think you should use it:

public interface IEntity
{
    int Id { get; }
}

public interface IRepository<T> where T : class, IEntity 
{
    IQueryable<T> GetQuery();
    T Get(int id);
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
}

执行:

public Repository<T> where T : class, IEntity
{
    private ObjectSet<T> _set;          // or DbSet
    private ObjectContext _context;  // or DbContext

    public Repository(ObjectContext context) // or DbContext
    {
        _context = context;
        _set = context.CreateObjectSet<T>();  // _context.Set<T>() for DbContext                     
    }

    public IQueryable<T> GetQuery()
    {
        return _set;
    }

    public T Get(int id)
    {
        return _set.SingleOrDefault(e => e.Id == id);
    }

    public void Add (T entity)
    {
        _set.AddObject(entity);
    }

    public void Update(T entity)
    {
        _set.Attach(entity);
        context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
        // or context.Entry(entity).State = EntityState.Modified; for DbContext
    }

    public void Delete(entity)
    {
        _set.Attach(entity);
        _set.DeleteObject(entity);
    }
}

否AcceptAllChanges ,因为它会重置 ObjectStateManager 键,您的更改将不会被保存。有没有娱乐的对象,因为它没有任何意义。

There is NO AcceptAllChanges because it will reset ObjectStateManager and your changes will never be saved. There is no recreation of objects because it doesn't make sense.

使用这个仓库就是这么简单:

Using this repository is as simple as:

var repo = new BaseRepository<Product>(context);
repo.Add(new Product() { ... });
repo.Add(new Scale() { ... }); // yes this works because derived entities are handled by the same set
context.Save();

这篇关于Repository模式和继承在.net中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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