entity-framework - 将库从 ObjectContext 转换为 DbContext

标签 entity-framework entity-framework-4.1 objectcontext dbcontext

我有一个库 ( based on code found in an old blog post ),它允许我使用 Entity Framework 非常轻松地围绕我的数据访问包装外观。它使用 ObjectContext 并且对于我的目的来说已经足够好了。

但现在,我们正在兴奋地使用 DbContext 研究代码优先,当然希望尽可能多地重用/调整我们现有的工作。

当我们尝试使用我们的外观时,在收到以下错误时,一切都顺利地使用 IObjectContextAdapter 转换我们的外观启用库:

The type 'Employee' cannot be used as type parameter 'TEntity' in the generic type or method 'DbContextManagement.FacadeBase'. There is no implicit reference conversion from 'Employee' to 'System.Data.Objects.DataClasses.EntityObject'

MSDN 说:

EntityObject derived types are not supported by the DbContext API, to use these entity types you must use the ObjectContext API.

那很好,但是我该如何继续完成我的重构以绕过这种无能为力呢?

这是一些代码(引入了换行符):

FacadeBase.cs

namespace DbContextManagement
{
    using System;
    using System.Collections;
    using System.Configuration;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Data.Metadata.Edm;
    using System.Data.Objects.DataClasses;
    using System.Linq;
    using System.Reflection;

    public abstract class FacadeBase<TDbContext, TEntity>
        where TDbContext : DbContext, new()
        where TEntity : EntityObject
    {
        protected TDbContext DbContext
        {
            get
            {
                if (DbContextManager == null)
                {
                    this.InstantiateDbContextManager();
                }

                return DbContextManager.GetDbContext<TDbContext>();
            }
        }

        private DbContextManager DbContextManager { get; set; }

        public virtual void Add(TEntity newObject)
        {
            var context = ((IObjectContextAdapter)this.DbContext).ObjectContext;

            string entitySetName;

            if (newObject.EntityKey != null)
            {
                entitySetName = newObject.EntityKey.EntitySetName;
            }
            else
            {
                string entityTypeName = newObject.GetType().Name;

                var container = context.MetadataWorkspace.GetEntityContainer(
                                    context.DefaultContainerName, 
                                    DataSpace.CSpace);

                entitySetName = (from meta in container.BaseEntitySets
                                    where meta.ElementType.Name == 
                                       entityTypeName
                                    select meta.Name).First();
            }

            context.AddObject(entitySetName, newObject);
        }

        public virtual void Delete(TEntity obsoleteObject)
        {
            var context = ((IObjectContextAdapter)this.DbContext).ObjectContext;

            context.DeleteObject(obsoleteObject);
        }

        private void InstantiateDbContextManager()
        {
            var objectContextManagerConfiguration = 
               ConfigurationManager.GetSection("DbContext") as Hashtable;

            if (objectContextManagerConfiguration != null && 
                objectContextManagerConfiguration.ContainsKey("managerType"))
            {
                var managerTypeName = 
                   objectContextManagerConfiguration["managerType"] as string;

                if (string.IsNullOrEmpty(managerTypeName))
                {
                    throw new ConfigurationErrorsException(
                        "The managerType attribute is empty.");
                }

                managerTypeName = managerTypeName.Trim().ToLower();

                try
                {
                    var frameworkAssembly = 
                         Assembly.GetAssembly(typeof(DbContextManager));

                    var managerType = 
                         frameworkAssembly.GetType(managerTypeName, true, true);

                    this.DbContextManager = 
                        Activator.CreateInstance(managerType) as DbContextManager;
                }
                catch (Exception e)
                {
                    throw new ConfigurationErrorsException(
                        "The managerType specified in the 
                            configuration is not valid.", e);
                }
            }
            else
            {
                throw new ConfigurationErrorsException(
    "A Facade.DbContext tag or its managerType attribute
    is missing in the configuration.");
            }
        }
    }
}

EmployeeFacade.cs

namespace Facade
{
    using System.Collections.Generic;
    using System.Linq;
    using DataModel;
    using DataModel.Entities;
    using DbContextManagement;

    public sealed class EmployeeFacade : FacadeBase<FleetContext, Employee>
    {
        public Employee GetById(int? employeeId)
        {
            return employeeId == null
                ? null
                : this.DbContext.Employees.FirstOrDefault(m => m.Id == employeeId);
        }
    }
}

Employee.cs

namespace DataModel.Entities
{
    public class Employee
    {
        public int Id { get; set; }
        public string Surname { get; set; }
        public string Forename { get; set; }
        public string EmployeeNumber { get; set; }
    }
}

最佳答案

如果您的实体派生自 EntityObject 并且您要重用的代码依赖于基于 EntityObject 的实体,那么它就是一个阻碍。在您的实体是 POCO(没有 EntityObject 父级)之前,您不能使用 DbContext API。

顺便说一句。您可以使用 ObjectContext(和 POCO)的仅代码映射,而无需使用 DbContext。您只需要:

  • 为描述映射的每个 POCO 实体/复杂类型创建基于 EntityTypeConfigurationComplexTypeConfiguration 的类
  • 使用DbModelBuilder 收集您的配置并调用Build 获取DbModel 实例
  • 在您的 DbModel 实例上调用 Compile 以获取 DbCompiledModel
  • 在应用程序的生命周期内缓存编译模型
  • 当您需要一个新的 ObjectContext 实例时,在已编译模型上调用 CreateObjectContext

请注意,代码映射的功能集非常有限,因此并非您当前在 EDMX 中拥有的所有内容都可以通过代码映射实现。

关于entity-framework - 将库从 ObjectContext 转换为 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8423736/

相关文章:

c# - EF Core 模型之间没有完整引用

c# - 单元测试和 Entity Framework

wcf - 企业解决方案中的 Entity Framework

c# - Linq/ Entity Framework 中的对象和上下文有什么区别

c# 在多线程服务器中使用 Entity Framework

c# - 使用 Entity Framework 搜索单个项目并将其作为数据传输对象返回?

c# - 多个数据库提供者的一个 Entity Framework 模型

entity-framework-4.1 - 拥有所有实体派生自的 BaseEntity 类型或接口(interface)更好吗?

c# - 关闭任何上下文实例的 EF 更改跟踪

entity-framework-4.1 - 如何使用测试数据轻松填充 Entity Framework 上下文初始值设定项?