0

是否可以将基于 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 - EF But without getting into the Runtime Error

System.InvalidCastException: 'Unable to cast object of type 
'System.Data.Entity.DynamicProxies.Entity_33C84C30E063218CBB4881E395838375014F3EFBA09108F25ACF2FB2FCA1E92D' 
to type 'EntityTypes.IEntity'.'
4

2 回答 2

1

包含实际数据库实体的接口并针对 EF 6 和 EF Core 5 支持的框架平台的项目?

基本上,这很简单。您不需要任何实体接口。只需在您从两个 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();

}

您必须添加方法来获取成形数据,因为预先加载Include是特定于版本的扩展,或者提供将表达式传递到抽象存储库并Include在特定于版本的子类中创建的方法。但是使用 IQueryable 的基本查询可以正常工作。

于 2021-10-14T15:51:59.030 回答
0

我最终做了以下事情:

//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) 中通过包含的外部接口与包含的外部实体类型重用数据库访问代码。

于 2021-10-16T08:12:39.873 回答