EntityFramework 存储库从接口和抽象类驱动:如何在 ASP.NET MVC 上使用依赖项注入

发布于 2024-12-07 13:35:11 字数 7808 浏览 0 评论 0原文

好吧,让我分解一下我一直在尝试做的事情:

首先,这是我的 abstract 通用存储库:

public abstract class Repository<T, C> where T : class where C : DbContext, new() {

    private C _entities = new C();

    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) {

        IQueryable<T> query = _entities.Set<T>().Where(predicate);
        return query;
    }

    public void Add(T entity) {
        _entities.Set<T>().Add(entity);
    }

    public void Delete(T entity) {
        _entities.Set<T>().Remove(entity);
    }

    public void Edit(T entity) {
        _entities.Entry(entity).State = System.Data.EntityState.Modified;
    }

    public void Save() {
        _entities.SaveChanges();
    }
}

另外,这是我将用于我的 AccommPropertyWebDetailRepository< 的接口/code> 存储库 class

public interface IAccommPropertyWebDetailRepository {

    IQueryable<AccommPropertyWebDetail> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All);

    AccommPropertyWebDetail GetSingle(int accommPropertyWebDetailId, ApprovalStatus approvalstatus = ApprovalStatus.All);
    AccommPropertyWebDetail GetSingleByAccommPropertyId(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All);
}

下面是我的 AccommPropertyWebDetailRepository 类:

public class AccommPropertyWebDetailRepository : Repository<AccommPropertyWebDetail, ReservationHubEntities>, IAccommPropertyWebDetailRepository {

        ReservationHubEntities _entities = new ReservationHubEntities();

        public IQueryable<AccommPropertyWebDetail> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All) {

            IQueryable<AccommPropertyWebDetail> query = _entities.AccommPropertyWebDetails;
            switch (approvalstatus) {

                case ApprovalStatus.Approved:
                    query = query.Where(x => (x.AccommProperty.IsApproved == true) && (x.AccommProperty.IsLockedForView == false));
                    break;

                case ApprovalStatus.NotApproved:
                    query = query.Where(x => (x.AccommProperty.IsApproved == false) || (x.AccommProperty.IsLockedForView == true));
                    break;
            }
            return query;
        }

        public AccommPropertyWebDetail GetSingle(int accommPropertyWebDetailId, ApprovalStatus approvalstatus = ApprovalStatus.All) {
            var query = GetAll(approvalstatus).First(x => x.AccommPropertyWebDetailID == accommPropertyWebDetailId);
            return query;
        }

        public AccommPropertyWebDetail GetSingleByAccommPropertyId(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All) {
            var query = GetAll(approvalstatus).Single(x => x.AccommPropertyID == accommPropertyId);
            return query;
        }
}

所以到目前为止一切都很好(根据我的说法,但我是不知道我错过了什么)。

我遇到的真正问题是在 ASP.NET MVC Web 应用程序方面。

假设我的控制器类如下启动:

public AccommPropertyController(
    IAccommPropertyPictureRepository accommpropertypicturerepo) {

    _accommpropertypicturerepo = accommpropertypicturerepo;
}

private readonly IAccommPropertyPictureRepository _accommpropertypicturerepo;

对于依赖项注入,我有以下代码(我使用 Ninject 进行依赖项注入):

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel) {

    kernel.Bind<IAccommPropertyPictureRepository>().
        To<AccommPropertyPictureRepository>();

}  

那么, Repository 抽象类应该在哪里适合这里吗?

因为,我没有直接在控制器内部使用 AccommPropertyPictureRepository ,而只使用 IAccommPropertyPictureRepository 接口,所以我的控制器不知道任何关于 Repository< /code> 抽象类。

有什么已知的方法可以处理这个恼人的问题吗?

更新1

所以,现在在@Darin的建议之后,我有以下接口

public interface IRepository<T, C> where T : class where C : DbContext {

    IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
    void Add(T entity);
    void Delete(T entity);
    void Edit(T entity);
    void Save();

}

并且我的抽象类如下:

public abstract class Repository<T, C> : IRepository<T, C> where T : class where C : DbContext, new() {

    private C _entities = new C();

    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) {

        IQueryable<T> query = _entities.Set<T>().Where(predicate);
        return query;
    }

    public void Add(T entity) {
        _entities.Set<T>().Add(entity);
    }

    public void Delete(T entity) {
        _entities.Set<T>().Remove(entity);
    }

    public void Edit(T entity) {
        _entities.Entry(entity).State = System.Data.EntityState.Modified;
    }

    public void Save() {
        _entities.SaveChanges();
    }
}

无法弄清楚其余部分。

更新2

现在我也想出了一些办法。这是 IAccommPropertyPictureRepository 接口:

public interface IAccommPropertyPictureRepository<T, C> : IRepository<T, C> where T : class where C : DbContext {

    IQueryable<AccommPropertyPicture> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All);
    IQueryable<AccommPropertyPicture> GetAll(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All);

    AccommPropertyPicture GetSingle(int accommPropertyPictureId, ApprovalStatus approvalstatus = ApprovalStatus.All);
    AccommPropertyPicture GetSingle(Guid accommPropertyPictureGUID, ApprovalStatus approvalstatus = ApprovalStatus.All);

}

这是 AccommPropertyPictureRepository 类:

public class AccommPropertyPictureRepository : Repository<AccommPropertyPicture, ReservationHubEntities>, IAccommPropertyPictureRepository<AccommPropertyPicture, ReservationHubEntities> {

    ReservationHubEntities _entities = new ReservationHubEntities();

    public IQueryable<AccommPropertyPicture> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All) {

        IQueryable<AccommPropertyPicture> query = _entities.AccommPropertyPictures;

        switch (approvalstatus) {

            case ApprovalStatus.Approved:
                query = query.Where(x => (x.AccommProperty.IsApproved == true) && (x.AccommProperty.IsLockedForView == false));
                break;

            case ApprovalStatus.NotApproved:
                query = query.Where(x => (x.AccommProperty.IsApproved == false) || (x.AccommProperty.IsLockedForView == true));
                break;

        }

        return query;
    }

    public IQueryable<AccommPropertyPicture> GetAll(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All) {

        var query = GetAll(approvalstatus).Where(x => x.AccommPropertyID == accommPropertyId);

        return query;
    }

    public AccommPropertyPicture GetSingle(int accommPropertyPictureId, ApprovalStatus approvalstatus = ApprovalStatus.All) {

        var query = GetAll(approvalstatus).First(x => x.AccommPropertyPictureID == accommPropertyPictureId);

        return query;
    }

    public AccommPropertyPicture GetSingle(Guid accommPropertyPictureGUID, ApprovalStatus approvalstatus = ApprovalStatus.All) {

        var query = GetAll(approvalstatus).First(x => x.AccommPropertyPictureGUID == accommPropertyPictureGUID);

        return query;
    }
}

我现在已经成功构建了。 Ninject 的东西应该保持不变吗?我想我只需要更改控制器构造函数中的一些代码,对吗?

Ok, let me break down what I have been trying to do :

First of all here is the abstract generic repository of mine :

public abstract class Repository<T, C> where T : class where C : DbContext, new() {

    private C _entities = new C();

    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) {

        IQueryable<T> query = _entities.Set<T>().Where(predicate);
        return query;
    }

    public void Add(T entity) {
        _entities.Set<T>().Add(entity);
    }

    public void Delete(T entity) {
        _entities.Set<T>().Remove(entity);
    }

    public void Edit(T entity) {
        _entities.Entry(entity).State = System.Data.EntityState.Modified;
    }

    public void Save() {
        _entities.SaveChanges();
    }
}

Also, here is an interface which I will use for my AccommPropertyWebDetailRepository repository class :

public interface IAccommPropertyWebDetailRepository {

    IQueryable<AccommPropertyWebDetail> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All);

    AccommPropertyWebDetail GetSingle(int accommPropertyWebDetailId, ApprovalStatus approvalstatus = ApprovalStatus.All);
    AccommPropertyWebDetail GetSingleByAccommPropertyId(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All);
}

And the below one is my AccommPropertyWebDetailRepository class :

public class AccommPropertyWebDetailRepository : Repository<AccommPropertyWebDetail, ReservationHubEntities>, IAccommPropertyWebDetailRepository {

        ReservationHubEntities _entities = new ReservationHubEntities();

        public IQueryable<AccommPropertyWebDetail> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All) {

            IQueryable<AccommPropertyWebDetail> query = _entities.AccommPropertyWebDetails;
            switch (approvalstatus) {

                case ApprovalStatus.Approved:
                    query = query.Where(x => (x.AccommProperty.IsApproved == true) && (x.AccommProperty.IsLockedForView == false));
                    break;

                case ApprovalStatus.NotApproved:
                    query = query.Where(x => (x.AccommProperty.IsApproved == false) || (x.AccommProperty.IsLockedForView == true));
                    break;
            }
            return query;
        }

        public AccommPropertyWebDetail GetSingle(int accommPropertyWebDetailId, ApprovalStatus approvalstatus = ApprovalStatus.All) {
            var query = GetAll(approvalstatus).First(x => x.AccommPropertyWebDetailID == accommPropertyWebDetailId);
            return query;
        }

        public AccommPropertyWebDetail GetSingleByAccommPropertyId(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All) {
            var query = GetAll(approvalstatus).Single(x => x.AccommPropertyID == accommPropertyId);
            return query;
        }
}

So everything has been fine so far (according to me but I am not sure what I am missing).

The real problem I have is on the ASP.NET MVC Web application side.

Let's assume that my controller class starts as follows :

public AccommPropertyController(
    IAccommPropertyPictureRepository accommpropertypicturerepo) {

    _accommpropertypicturerepo = accommpropertypicturerepo;
}

private readonly IAccommPropertyPictureRepository _accommpropertypicturerepo;

And for dependency injection, I have the following code (I am using Ninject for Dependency Injection) :

/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel) {

    kernel.Bind<IAccommPropertyPictureRepository>().
        To<AccommPropertyPictureRepository>();

}  

So, where is Repository<T, C> abstract class supposed to fit in here?

Because, I didn't directly use AccommPropertyPictureRepository inside my controller and only used IAccommPropertyPictureRepository interface, my controller doesn't know anything about Repository<T, C> abstract class.

Any known ways of dealing with this annoying issue?

UPDATE 1

So, now after @Darin's suggestion, I have following interface

public interface IRepository<T, C> where T : class where C : DbContext {

    IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
    void Add(T entity);
    void Delete(T entity);
    void Edit(T entity);
    void Save();

}

And my abstract class is as follows :

public abstract class Repository<T, C> : IRepository<T, C> where T : class where C : DbContext, new() {

    private C _entities = new C();

    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) {

        IQueryable<T> query = _entities.Set<T>().Where(predicate);
        return query;
    }

    public void Add(T entity) {
        _entities.Set<T>().Add(entity);
    }

    public void Delete(T entity) {
        _entities.Set<T>().Remove(entity);
    }

    public void Edit(T entity) {
        _entities.Entry(entity).State = System.Data.EntityState.Modified;
    }

    public void Save() {
        _entities.SaveChanges();
    }
}

Can't figure the rest of it out.

UPDATE 2

Now I have figured something out as well. Here is IAccommPropertyPictureRepository interface :

public interface IAccommPropertyPictureRepository<T, C> : IRepository<T, C> where T : class where C : DbContext {

    IQueryable<AccommPropertyPicture> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All);
    IQueryable<AccommPropertyPicture> GetAll(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All);

    AccommPropertyPicture GetSingle(int accommPropertyPictureId, ApprovalStatus approvalstatus = ApprovalStatus.All);
    AccommPropertyPicture GetSingle(Guid accommPropertyPictureGUID, ApprovalStatus approvalstatus = ApprovalStatus.All);

}

and here is the AccommPropertyPictureRepository class :

public class AccommPropertyPictureRepository : Repository<AccommPropertyPicture, ReservationHubEntities>, IAccommPropertyPictureRepository<AccommPropertyPicture, ReservationHubEntities> {

    ReservationHubEntities _entities = new ReservationHubEntities();

    public IQueryable<AccommPropertyPicture> GetAll(ApprovalStatus approvalstatus = ApprovalStatus.All) {

        IQueryable<AccommPropertyPicture> query = _entities.AccommPropertyPictures;

        switch (approvalstatus) {

            case ApprovalStatus.Approved:
                query = query.Where(x => (x.AccommProperty.IsApproved == true) && (x.AccommProperty.IsLockedForView == false));
                break;

            case ApprovalStatus.NotApproved:
                query = query.Where(x => (x.AccommProperty.IsApproved == false) || (x.AccommProperty.IsLockedForView == true));
                break;

        }

        return query;
    }

    public IQueryable<AccommPropertyPicture> GetAll(int accommPropertyId, ApprovalStatus approvalstatus = ApprovalStatus.All) {

        var query = GetAll(approvalstatus).Where(x => x.AccommPropertyID == accommPropertyId);

        return query;
    }

    public AccommPropertyPicture GetSingle(int accommPropertyPictureId, ApprovalStatus approvalstatus = ApprovalStatus.All) {

        var query = GetAll(approvalstatus).First(x => x.AccommPropertyPictureID == accommPropertyPictureId);

        return query;
    }

    public AccommPropertyPicture GetSingle(Guid accommPropertyPictureGUID, ApprovalStatus approvalstatus = ApprovalStatus.All) {

        var query = GetAll(approvalstatus).First(x => x.AccommPropertyPictureGUID == accommPropertyPictureGUID);

        return query;
    }
}

I have a successful build now. Should Ninject stuff stay unchanged? I think I only need to change some of the code from my controller constructor, right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

征﹌骨岁月お 2024-12-14 13:35:11

一种可能性是拥有一个包含所有必要操作的基本 IRepository 接口,并将由 Repository 抽象类实现为以及通过 IAccommPropertyWebDetailRepository 接口。

One possibility would be to have a base IRepository<T, C> interface containing all the necessary operations and which will be implemented by the Repository<T, C> abstract class as well as by the IAccommPropertyWebDetailRepository interface.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文