我有一个库 ( 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 实体/复杂类型创建基于
EntityTypeConfiguration
或ComplexTypeConfiguration
的类 - 使用
DbModelBuilder
收集您的配置并调用Build
获取DbModel
实例 - 在您的
DbModel
实例上调用Compile
以获取DbCompiledModel
- 在应用程序的生命周期内缓存编译模型
- 当您需要一个新的
ObjectContext
实例时,在已编译模型上调用CreateObjectContext
请注意,代码映射的功能集非常有限,因此并非您当前在 EDMX 中拥有的所有内容都可以通过代码映射实现。
关于entity-framework - 将库从 ObjectContext 转换为 DbContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8423736/