简体   繁体   中英

WCF Service with EntityFramework, giving error “The type 'DBContext' is defined in an assembly that is not referenced”

I am working on a WCF Service application which is using EF for data access. All my EF models under DataLayer. I have created following factory method under data layer

namespace TRA.Services.DataAccessLayer
{
    public static class DataObjectFactory
    {
        public static TRAEntities CreateTRAContext()
        {
            return new TRAEntities();
        }
    }
}

In business layer I am trying to use following code :

using (var context = DataObjectFactory.CreateTRAContext())
            {
                var objClients = from r in context.TRAEmployee
                                 orderby r.id
                                 select r;
            }

It gives me following error : "The type 'DBContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'EntityFramework, Version=6.0.0.0,......"

Since I am using this code in business layer I dont want to add reference to EntityFramework.

Is there any way to handle this scenario?

Every type in the inheritance tree of types you publicly expose from a class member in an assembly ( public static TRAEntities where TRAEntities : DbContext ) must be known to referencing assemblies if they want to use that member.

So because you're exposing and accessing DataObjectFactory.CreateTRAContext() from your business layer, and the type returned from that method inherits from Entity Framework's DbContext , your business layer needs a reference to Entity Framework.

You can solve this problem by introducing a layer of indirection, in this case generally done through some repository layer. This also makes your business layer testable without having to mock Entity Framework.

So instead of pulling in the DbContext from your data layer and accessing its DbSet<T> members, you expose repositories which in turn expose the entities you want to access:

public interface IRepository<T>
{
    IQueryable<T> Entries();
}

The implementation of this repository is internal to the data layer, and wraps a DbSet<T> DbContext.Set<T> .

The problem here is more of a conceptual nature. Instead of exposing a method that returns an instance of TRAEntities , you should create an Accessor that returns the employees list to the bsuness logic layer, such as:

IEnumerable<Employee> GetEmployees()
{
    IEnumerable<Employee> employees;

    using (var context = DataObjectFactory.CreateTRAContext())
    {
        employees = from r in context.TRAEmployee
                    orderby r.id
                    select r;
    }

    return employees;
}

Additionally, if abstraction between layers is important, implement a separate Employee entity for moving the data out of the data access layer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM