You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

配置EF Core模型时遇CS0311错误,求原因及相关解惑

EF Core模型配置中GetProperties方法的CS0311错误排查

问题背景

为遵循DRY原则复用代码,配置EF Core模型时编写了GetProperties方法筛选所有实体类型的属性,但触发编译错误。

问题代码

public List<IMutableProperty> GetProperties(ModelBuilder modelBuilder, Func<IProperty, bool> filter)
{
    var properties = modelBuilder.Model
        .GetEntityTypes()
        .SelectMany(t => t.GetProperties())
        .ToList()
        .Where(filter) // 此行触发错误
        .ToList();
    return properties;
}

错误信息

error CS0311: The type 'Microsoft.EntityFrameworkCore.Metadata.IProperty' cannot be used as type parameter 'TRow' in the generic type or method 'TypedTableBaseExtensions.Where(TypedTableBase, Func<TRow, bool>)'. There is no implicit reference conversion from 'Microsoft.EntityFrameworkCore.Metadata.IProperty' to 'System.Data.DataRow'.

使用示例

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    ConfigureTenants(modelBuilder);
    ConfigureLocales(modelBuilder);
    ConfigureKeys(modelBuilder);
    ConfigureGuids(modelBuilder);
    ConfigureSlugs(modelBuilder);
    ConfigureOrders(modelBuilder);
    ConfigRelatedItems(modelBuilder);
}

public void ConfigureTenants(ModelBuilder modelBuilder)
{
    var properties = GetProperties(modelBuilder, p => p.ClrType == typeof(string) && p.Name == "Tenant");
    properties.ForEach(p => p.SetDefaultValue("'main'"));
}

public void ConfigureLocales(ModelBuilder modelBuilder)
{
    var properties = GetProperties(modelBuilder, p => p.ClrType == typeof(string) && p.Name == "Locale");
    properties.ForEach(p => p.SetDefaultValue("'en'"));
}

疑问

为何会出现该错误?此代码与TRow究竟有何关联?


错误原因与修复方案

错误原因

问题出在调用.ToList()后再使用.Where():编译器错误绑定了System.Data.DataSetExtensions命名空间下的TypedTableBaseExtensions.Where方法(该方法专为DataRow类型的表设计),而非LINQ的Enumerable.Where扩展方法。

具体逻辑:

  1. 先将EF Core属性集合转为List<IProperty>
  2. 编译器找不到匹配的LINQ Where时,误匹配了另一个命名空间的Where方法,而该方法要求参数为DataRow类型,与IProperty不兼容,因此触发类型转换错误。

修复方案

方案一:移除多余的.ToList()

让Where直接作用于EF Core返回的可枚举集合,编译器会正确绑定LINQ的Enumerable.Where方法:

public List<IMutableProperty> GetProperties(ModelBuilder modelBuilder, Func<IProperty, bool> filter)
{
    var properties = modelBuilder.Model
        .GetEntityTypes()
        .SelectMany(t => t.GetProperties())
        .Where(filter)
        .ToList();
    return properties;
}

方案二:显式指定LINQ方法(不推荐,仅作演示)

若必须先转List再过滤,可通过AsEnumerable()将集合转为IEnumerable<T>,引导编译器找到正确的Where方法:

using System.Linq;

// ...

var properties = modelBuilder.Model
    .GetEntityTypes()
    .SelectMany(t => t.GetProperties())
    .ToList()
    .AsEnumerable()
    .Where(filter)
    .ToList();

额外提示

注意默认值写法:SetDefaultValue("'main'")会将带单引号的字符串作为默认值,若要设置的是字符串main而非'main',应改为SetDefaultValue("main")。


内容的提问来源于stack exchange,提问作者Hasan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 20:12:34