Click here to Skip to main content
15,861,168 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
Hi,

For all my applications (ASP.NET MVC3, EF Code First), I have this general pattern that i'm using:

Entity:

C#
public class Product 
    { 
        public int ProductID { get; set; } 
 
        public string Name { get; set; } 
 
        public string Category { get; set; } 
 
        public decimal Price { get; set; } 
    }


EFDbContext:

C#
public class EFDbContext : DbContext 
    { 
        public DbSet<Product> Products { get; set; } 
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder) 
        { 
            // Product 
            modelBuilder.Entity<Product>() 
                .HasKey(p => p.ProductID) 
                .Property(p => p.ProductID)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
 
      
        } 
    }


I have a Generic Repository, which will be used by my Unit Of Work class, as below:

C#
public class UnitOfWork : IUnitOfWork, IDisposable 
    { 
        private readonly EFDbContext context; 
        private IGenericRepository<Product> _productRepository; 
 
        
        public UnitOfWork() 
        { 
            context = new EFDbContext(); 
        } 
        
        public EFDbContext Context 
        { 
            get 
            { 
                return context; 
            } 
        } 
 
        public IGenericRepository<Product> ProductRepository 
        { 
            get 
            { 
                if (_productRepository == null) 
                { 
                    _productRepository = new 
                                         GenericRepository<Product>(context); 
                } 
                return _productRepository; 
            } 
        } 
 
       // save() 
       // Dispose() & so on.. left out


I have a Service Layer, which as it should, models business logic. This layer, uses Unit Of Work, as below:

C#
public class ProductService : IProductService 
    { 
        private IUnitOfWork unitOfWork; 
 
        public ProductService(IUnitOfWork unitOfWorkParam) 
        { 
            unitOfWork = unitOfWorkParam; 
        } 
 
        public void AddProduct(Product product) 
        { 
            unitOfWork.ProductRepository.Insert(product); 
            unitOfWork.Save(); 
        } 
        // other services for business logic.. 
    }


Now, my UI project (ASP.NET MVC3), uses the service layer as below

C#
public class HomeController : Controller 
    { 
        private IProductService productService; 
 
        public HomeController(IProductService productServiceParam) 
        { 
            productService = productServiceParam; 
        } 
 
        public ActionResult Products() 
        { 
            // User productService.GetProducts and so on 
        } 
    }


Thus the whole setup of the Projects to summazie would be:

Controller --> Service Layer --> UnitOfWork (which contains context, repositories)
--> DB

Now, my question is, the EFDbContext is contained in UnitOfWork, and thus, in this class, we can use queries such as:

C#
using (var context = new EFDbContext()) 
{ 
    // use context.Entry<> 
    // use context.Find<> 
    // use context.Attach<> 
    // and other useful functions 
}


but, how can i get this functionality migrated to my Service Layer, which uses UnitOfWork.Repositories ?

Have i missed something in design?

It would be great to have the Service Layer capable somehow of using the bare context object, where in we can use useful extension methods such as context.Entry<> ..

Can anyone please help me with this?

thanks.
Posted
Comments
robroysd 5-Aug-12 18:58pm    
FYI, for my own reference, and for anyone interested, i had posted the same issue on forums.asp.net, here's the link

http://forums.asp.net/t/1830559.aspx/1?EF+Code+First+Using+DbContext+in+Service+Layer+Help+Needed

1 solution

This looks complex. Why don't you use annotations on your class to define keys, etc ? For example, [Table("Product")] above the class and [Key] above the ProductId.

In my code, the DbContext has a private constructor, and a public static instance property, which returns the same instance across requests for the same session ( it uses the session key to do this ). I can access my DBContext from anywhere in my project, but I don't break it up in to dlls, so perhaps your issue is one of what dlls are consumed where ?
 
Share this answer
 
Comments
robroysd 4-Aug-12 18:13pm    
I can use data annotations, but i use Fluent API so as to have all relationship maps at one place.
For example:
// Product:
// define product properties such as <Product>().has key etc etc
// define relations such as <Product>().HasMany(SomeList).WithRequired()..

This way, i can have everything in one place, i.e. the modelBuilder object.

I will look into the DbContext --> public static instance. Thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900