将 EF6 和 EFCore 实体转换为单个接口?
Cast EF6 and EFCore Entity to a single Interface?
是否可以从基于 EF 6(使用 .NetFramework 4.0)和 EF Core 5.0( .Net Standard 2.1) 使用相同的数据库 到一个实体接口 而不是使用两个实体框架提供的实际数据库 类,使用包含实际数据库接口的项目EF 6 和 EF Core 5 支持的框架平台的实体和目标?
<!--EntityTypes.csproj-->
...
<TargetFrameworks>netstandard2.1; net40; net45</TargetFrameworks>
....
// IEntity.cs
namespace EntityTypes
{
public interface IEntity
{
long EntityID { get; set; }
string EntityName { get; set; }
}
}
在 .Net Core 和 Framework 4.0 项目中,我需要以某种方式使用像
这样的语法
var _entitiesContext = new EntitiesContext();
public static List<IEntity> BuildSet<T>() where T : class
{
return _entitiesContext.Entities.ToList().Cast<IEntity>().ToList();
}
正如我已经在这个问题中发现的那样:How to Cast DBSet to Interface in Anonymous Method - E.F
但是没有进入运行时错误
System.InvalidCastException: 'Unable to cast object of type
'System.Data.Entity.DynamicProxies.Entity_33C84C30E063218CBB4881E395838375014F3EFBA09108F25ACF2FB2FCA1E92D'
to type 'EntityTypes.IEntity'.'
a project that contains Interfaces of the actual DataBase Entities and targets both EF 6 and EF Core 5 supported framework platforms?
基本上,这很简单。您不需要任何实体接口。只需在您从两个 EF 项目引用的单独程序集中定义您的实体,并创建一个抽象 class 或接口来定义您可以使用 EF Core 或 EF6 DbContext 实现的存储库,例如:
public class SomeEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class AnotherEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class Repository : IDisposable
{
public abstract IQueryable<SomeEntity> SomeEntities { get; }
public abstract IQueryable<AnotherEntity> AnotherEntities { get; }
public abstract void SaveChanges();
public abstract void Dispose();
}
您必须添加方法来获取整形数据,因为使用 Include
进行预加载是特定于版本的扩展,或者提供将表达式传递到抽象存储库并创建 Include
的方法在版本特定的 subclass 中。但是使用 IQueryable 的基本查询可以正常工作。
我最终做了以下事情:
//ContextTypes.csproj, IDBContext.cs
public interface IDBContext
{
void Add<TEntity>(TEntity e) where TEntity : class;
void Remove<TEntity>(TEntity e) where TEntity : class;
IQueryable<Entity> GetEntities();
int SaveChanges();
}
//ContextTypes.csproj, Entity.cs
public partial class Entity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
//...
}
//EntitiesContext.csproj, EntitiesContext.cs: (EF 6)
using ContextTypes;
public partial class EntitiesContext : DbContext, IDBContext
{
//...
public virtual DbSet<ContextTypes.Entity> Entities { get; set; }
public IQueryable<ContextTypes.Entity> GetEntities() { return Entities; }
public void AddEntity<TEntity>(TEntity item) where TEntity : class
{
if (typeof(TEntity) == typeof(Entity))
{
Entities.Add(item as Entity);
}
}
public void RemoveEntity<TEntity>(TEntity item) where TEntity : class
{
if (typeof(TEntity) == typeof(Entity))
{
Entities.Remove(item as Entity);
}
}
//...
}
//EntitiesContext.csproj, EntitiesContext.cs: (EFCore 5)
//...
public void AddEntity<TEntity>(TEntity item) where TEntity : class
{
Add(item);
}
public void RemoveEntity<TEntity>(TEntity item) where TEntity : class
{
Remove(item);
}
//...
我还将自动生成的 ADO.NET context.tt 实体从 EF 6 复制到 ContextTypes.csproj 并将原始实体设置为“内部”类;
现在可以在 EF 6(.Net Framework 4.0)和 EF Core 项目(.Net Core 3.1 || .Net Standard)中通过包含的外部接口与包含的外部实体类型重用数据库访问代码2.1).
是否可以从基于 EF 6(使用 .NetFramework 4.0)和 EF Core 5.0( .Net Standard 2.1) 使用相同的数据库 到一个实体接口 而不是使用两个实体框架提供的实际数据库 类,使用包含实际数据库接口的项目EF 6 和 EF Core 5 支持的框架平台的实体和目标?
<!--EntityTypes.csproj-->
...
<TargetFrameworks>netstandard2.1; net40; net45</TargetFrameworks>
....
// IEntity.cs
namespace EntityTypes
{
public interface IEntity
{
long EntityID { get; set; }
string EntityName { get; set; }
}
}
在 .Net Core 和 Framework 4.0 项目中,我需要以某种方式使用像
这样的语法var _entitiesContext = new EntitiesContext();
public static List<IEntity> BuildSet<T>() where T : class
{
return _entitiesContext.Entities.ToList().Cast<IEntity>().ToList();
}
正如我已经在这个问题中发现的那样:How to Cast DBSet to Interface in Anonymous Method - E.F 但是没有进入运行时错误
System.InvalidCastException: 'Unable to cast object of type
'System.Data.Entity.DynamicProxies.Entity_33C84C30E063218CBB4881E395838375014F3EFBA09108F25ACF2FB2FCA1E92D'
to type 'EntityTypes.IEntity'.'
a project that contains Interfaces of the actual DataBase Entities and targets both EF 6 and EF Core 5 supported framework platforms?
基本上,这很简单。您不需要任何实体接口。只需在您从两个 EF 项目引用的单独程序集中定义您的实体,并创建一个抽象 class 或接口来定义您可以使用 EF Core 或 EF6 DbContext 实现的存储库,例如:
public class SomeEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public class AnotherEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class Repository : IDisposable
{
public abstract IQueryable<SomeEntity> SomeEntities { get; }
public abstract IQueryable<AnotherEntity> AnotherEntities { get; }
public abstract void SaveChanges();
public abstract void Dispose();
}
您必须添加方法来获取整形数据,因为使用 Include
进行预加载是特定于版本的扩展,或者提供将表达式传递到抽象存储库并创建 Include
的方法在版本特定的 subclass 中。但是使用 IQueryable 的基本查询可以正常工作。
我最终做了以下事情:
//ContextTypes.csproj, IDBContext.cs
public interface IDBContext
{
void Add<TEntity>(TEntity e) where TEntity : class;
void Remove<TEntity>(TEntity e) where TEntity : class;
IQueryable<Entity> GetEntities();
int SaveChanges();
}
//ContextTypes.csproj, Entity.cs
public partial class Entity
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
//...
}
//EntitiesContext.csproj, EntitiesContext.cs: (EF 6)
using ContextTypes;
public partial class EntitiesContext : DbContext, IDBContext
{
//...
public virtual DbSet<ContextTypes.Entity> Entities { get; set; }
public IQueryable<ContextTypes.Entity> GetEntities() { return Entities; }
public void AddEntity<TEntity>(TEntity item) where TEntity : class
{
if (typeof(TEntity) == typeof(Entity))
{
Entities.Add(item as Entity);
}
}
public void RemoveEntity<TEntity>(TEntity item) where TEntity : class
{
if (typeof(TEntity) == typeof(Entity))
{
Entities.Remove(item as Entity);
}
}
//...
}
//EntitiesContext.csproj, EntitiesContext.cs: (EFCore 5)
//...
public void AddEntity<TEntity>(TEntity item) where TEntity : class
{
Add(item);
}
public void RemoveEntity<TEntity>(TEntity item) where TEntity : class
{
Remove(item);
}
//...
我还将自动生成的 ADO.NET context.tt 实体从 EF 6 复制到 ContextTypes.csproj 并将原始实体设置为“内部”类;
现在可以在 EF 6(.Net Framework 4.0)和 EF Core 项目(.Net Core 3.1 || .Net Standard)中通过包含的外部接口与包含的外部实体类型重用数据库访问代码2.1).