C# 如何首先为EF6数据库中的所有实体类创建一个未映射的公共抽象BaseEntity父级?

C# 如何首先为EF6数据库中的所有实体类创建一个未映射的公共抽象BaseEntity父级?,c#,entity-framework,entity-framework-6,ef-database-first,C#,Entity Framework,Entity Framework 6,Ef Database First,我试图为数据库实体类实现公共逻辑,所以我想为我的实体引入一个公共的、非映射的抽象基类,如下所示 public abstract class BaseEntity { public int Id { get; set; } public byte[] RowVersion { get; set; } } 我不想在数据库中表示这个基类,而只想在实体模型的逻辑级别上表示。该项目是数据库优先项目,具有EDMX模型。如果是先编写代码,我(我想)可以通过使用适当的EF注释(Key,等等)注

我试图为数据库实体类实现公共逻辑,所以我想为我的实体引入一个公共的、非映射的抽象基类,如下所示

public abstract class BaseEntity {
    public int Id { get; set; }
    public byte[] RowVersion { get; set; }
}
我不想在数据库中表示这个基类,而只想在实体模型的逻辑级别上表示。该项目是数据库优先项目,具有EDMX模型。如果是先编写代码,我(我想)可以通过使用适当的EF注释(Key,等等)注释基类属性来轻松实现这一点

但在EDMX中,我似乎无法选择一个不是实体本身的自定义基类型。当我试图添加一个新实体时,它抱怨它没有映射

我也尝试过使用具有上述两个属性的接口,如
IDbEntity
,但是当我编写一个类似以下的通用方法时(只是一个简单的示例),我得到了关于接口属性未映射的错误。似乎EF无法识别基本上
Id
access对应于非递归实体类型

public static TDbEntity[] GetByIds<TDbEntity>(this IQueryable<TDbEntity> queryable, int[] ids)
    where TDbEntity : IDbEntity
{
    return queryable.Where(e => ids.Contain(e.Id)).ToArray();
}
publicstatictdbentity[]GetByIds(此IQueryable可查询,int[]ids)
其中TDbEntity:IDbEntity
{
返回queryable.Where(e=>ids.Contain(e.Id)).ToArray();
}

首先使用数据库时,我根本找不到这种基类的可行选项。任何帮助都将不胜感激。

对于未来的读者,我将发布我当前的解决方案

根据@IvanStoev的评论,我使用接口技术唯一需要的就是
通用约束。因此,我的扩展方法的这个版本在实体查询上运行良好,实现了
IDbEntity
接口

public interface IDbEntity {
    int Id { get; }
}

...

public static TDbEntity[] GetByIds<TDbEntity>(this IQueryable<TDbEntity> queryable, int[] ids)
    where TDbEntity : class, IDbEntity
{
    return queryable.Where(e => ids.Contain(e.Id)).ToArray();
}
公共接口实体{
int Id{get;}
}
...
公共静态TDbEntity[]GetById(此IQueryable可查询,int[]ID)
其中tdbenty:class,IDbEntity
{
返回queryable.Where(e=>ids.Contain(e.Id)).ToArray();
}
然后我修改了我的Edmx T4型生成器文件,以便在需要的地方生成接口引用。我必须以下面的方式扩展下面的方法

public string EntityClassOpening(EntityType entity)
{
    var baseTypeNames = new List<string>();
    baseTypeNames.Add(_typeMapper.GetTypeName(entity.BaseType));

    var hasId = entity.Properties.Any(e => e.Name == @"Id" && _typeMapper.UnderlyingClrType(e.TypeUsage.EdmType) == typeof(int));

    if (hasId) {
        baseTypeNames.Add(@"IDbEntity");
    }

    return string.Format(
            CultureInfo.InvariantCulture,
            "{0} {1}partial class {2}{3}",
            Accessibility.ForType(entity),
            _code.SpaceAfter(_code.AbstractOption(entity)),
            _code.Escape(entity),
            _code.StringBefore(" : ", string.Join(", ", baseTypeNames.Where(e => !string.IsNullOrEmpty(e)))));
}
公共字符串EntityClassOpening(EntityType实体)
{
var baseTypeNames=新列表();
添加(_typeMapper.GetTypeName(entity.BaseType));
var hasId=entity.Properties.Any(e=>e.Name=@“Id”&&&u typeMapper.underyingclrtype(e.TypeUsage.EdmType)==typeof(int));
如果(hasId){
baseTypeNames.Add(@“IDbEntity”);
}
返回字符串格式(
CultureInfo.InvariantCulture,
“{0}{1}部分类{2}{3}”,
可访问性.ForType(实体),
_code.SpaceAfter(_code.AbstractOption(entity)),
_代码。转义(实体),
_code.StringBefore(“:”,string.Join(“,”,baseTypeNames.Where(e=>!string.IsNullOrEmpty(e‘‘‘)’);
}

将基类抽象化有什么具体原因吗?您可以让它成为一个带有注释的普通类,并从中继承…隐式实现的接口与泛型方法中的
class
约束相结合(例如
其中TDbEntity:class,IDbEntity
)通常有效。@Glenvanacker AFAIK首先使用数据库时,注释无法正常工作,因为所有映射信息都来自EDMX,但我可能错了。@IvanStoev谢谢,我错过了
约束,我将尝试一下。如果您先使用数据库,那么为什么需要基本实体?正如我所想,您的每个表都有
Id
,当从数据库生成时,EDXM会自行处理该Id