简体   繁体   English

将 EF6 和 EFCore 实体转换为单个接口?

[英]Cast EF6 and EFCore Entity to a single Interface?

Is it possible to join different version of Entity Framework (Core) Entities from two applications based on EF 6 (with .NetFramework 4.0) and EF Core 5.0 (.Net Standard 2.1) with the same DataBase into one Entity Interface instead of using the actual database classes that both entity frameworks provide, using a project that contains Interfaces of the actual DataBase Entities and targets both EF 6 and EF Core 5 supported framework platforms?是否可以将基于 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; }
    }
}

In both .Net Core and Framework 4.0 projects, I need to somehow use syntax like在 .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();
}

As I've already found in this question : How to Cast DBSet to Interface in Anonymous Method - EF But without getting into the Runtime Error正如我在这个问题中已经发现的: How to Cast DBSet to Interface in Anonymous Method - EF但没有进入运行时错误

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 6 和 EF Core 5 支持的框架平台的项目?

Basically, this is simple.基本上,这很简单。 You don't need any entity interfaces.您不需要任何实体接口。 Just define your entities in a separate assembly that you reference from both EF projects, and create an abstract class or interface that defines the repository that you can implement with either an EF Core or EF6 DbContext, eg:只需在您从两个 EF 项目中引用的单独程序集中定义您的实体,并创建一个抽象类或接口来定义您可以使用 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();

}

You'll have to add methods to get shaped data because eager loading with Include is a version-specific extension, or provide methods to pass expressions into your abstract repository and create the Include in the version-specific subclass.您必须添加方法来获取成形数据,因为使用Include进行预加载是特定于版本的扩展,或者提供将表达式传递到抽象存储库并在特定于版本的子类中创建Include的方法。 But basic queries with IQueryable will work fine.但是使用 IQueryable 的基本查询可以正常工作。

I've ended up doing the following:我最终做了以下事情:

//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);
    }
    //...

I've also copied the auto-generated ADO.NET context.tt Entities from EF 6 to ContextTypes.csproj and set the original ones to "internal" classes;我还将自动生成的 ADO.NET context.tt 实体从 EF 6 复制到 ContextTypes.csproj 并将原始实体设置为“内部”类;

Now it's possible to reuse the DataBase access code through the included external interface with the included external Entity types both in EF 6 (.Net Framework 4.0) and in EF Core projects (.Net Core 3.1 || .Net Standard 2.1).现在可以在 EF 6 (.Net Framework 4.0) 和 EF Core 项目 (.Net Core 3.1 || .Net Standard 2.1) 中通过包含的外部接口重用数据库访问代码和包含的外部实体类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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