开发者

Accessing stored procedures on a code generated DbContext with Entity Framework 4.1 with DDD

开发者 https://www.devze.com 2023-04-09 15:58 出处:网络
I\'m working on a large project using ASP.Net 开发者_JAVA技巧MVC 3, EF 4.1 and Ninject for Dependecy Injection. I\'ve read through many of the existing questions here regarding DDD, EF and the Reposit

I'm working on a large project using ASP.Net 开发者_JAVA技巧MVC 3, EF 4.1 and Ninject for Dependecy Injection. I've read through many of the existing questions here regarding DDD, EF and the Repository Pattern but I can't seem to find anyone incorporating stored procedures with these patterns.

I don't like the idea of implementing yet another repository pattern on top of what seems to already be a UnitOfWork/RepositoryPattern already defined with a DbContext. Also, I generally don't like the idea of creating Service and Repository classes for every type of entity in the system if possible.

The source of my problem stems from this common repository interface which everyone seems to use.

public interface IRepository<TEntity> where TEntity : class
{
    TEntity Get(Expression<Func<TEntity, bool>> whereClause);

    IEnumerable<TEntity> List();
    IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> whereClause);

    void Add(TEntity entity);
    void Delete(TEntity entity);

    // And so on...
}

That's great if all your queries can be in context of a single entity. Where this breaks for me is when I want to access a stored procedure. With EF 4.1 & Code Generatrion you can add stored procedures (e.g. SelectUser) and it will generate a context which looks something like this.

namespace MyCompany.Data.Database
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Data.Objects;

    using MyCompany.Domain.Entities;
    using MyCompany.Domain.Contracts;

    public partial class MyCompanyEntities : DbContext
    {
        public MyCompanyEntities()
            : base("name=MyCompanyEntities")
        {
            this.Configuration.LazyLoadingEnabled = false;
            this.Configuration.ProxyCreationEnabled = false;
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

        public DbSet<Order> Orders { get; set; }
        public DbSet<User> Users { get; set; }

        public virtual ObjectResult<User> SelectUser(Nullable<int> userId)
        {
            ((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);

            var userIdParameter = userId.HasValue ?
                new ObjectParameter("UserId", userId) :
                new ObjectParameter("UserId", typeof(int)); MyCompanyEntities x; x.

            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", userIdParameter);
        }

        public virtual ObjectResult<User> SelectUser(Nullable<int> userId, MergeOption mergeOption)
        {
            ((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(typeof(User).Assembly);

            var userIdParameter = userId.HasValue ?
                new ObjectParameter("UserId", userId) :
                new ObjectParameter("UserId", typeof(int));

            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<User>("SelectUser", mergeOption, userIdParameter);
        }
    }
}

As part of my DDD setup I have a UserService class and I would like to 'inject' a repository to its constructor. Many examples suggest that the constructor should accept an (IRepository<User> userRepository). This doesn't work for me. Stored procedures are generated on the DbContext class as a method and I am unable to see it.

The only thing I can think of is to either create another interface with the stored procedure methods on it. I don't really want to add it to the generic IRepository because then when you have an instance of IRepository<Order> you'll still see SelectUser which seems a bit odd. Maybe it's not a big deal?

Perhaps I'm going about this the wrong way. Should I not be bothering with creating an interface on top of my DbContext if I'm not trying to create a whole new repository pattern? I was really creating it for the dependency injection. Would it be wrong if the UserService constructor took a MyCompanyEntities instance instead of an interface?


What you found is natural. The problem is that generic repository is insufficient for real scenarios. It is only good for "base" implementation. You need specific repository for User entity which will expose method wrapping call to context exposed stored procedure.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号