c# - 使用 Entity Framework 在运行时动态选择列

标签 c# sql asp.net entity-framework formatexception

我有这样一个现有的功能

public int sFunc(string sCol , int iId)
{
    string sSqlQuery = "  select  " + sCol + " from TableName where ID = " +  iId ;
    // Executes query and returns value in column sCol
}

该表有四列用于存储整数值,我正在使用上述函数分别读取它们。

现在我正在将它转换为 Entity Framework。

public int sFunc(string sCol , int iId)
{
     return Convert.ToInt32(TableRepository.Entities.Where(x => x.ID == iId).Select(x => sCol ).FirstOrDefault());
}

但是上面的函数返回错误

input string not in correct format

因为它返回列名本身。

我不知道如何解决这个问题,因为我是 EF 的新手。

任何帮助将不胜感激

谢谢

最佳答案

对于 8 年后的 OP 没有用,但这个问题有很多观点,所以我认为对其他人有一个正确的答案可能会有帮助。

如果您使用 Entity Framework,您应该进行 Linq 投影 (Select()),因为这会导致在数据库端进行正确、高效的查询,而不是拉入整个实体。

使用 Linq Select()不过,您通常必须提供一个 lambda,因此将您的列/属性名称放在字符串中是这里的主要困难。

最简单的解决方案是使用动态 LINQ (EntityFramework.DynamicLinq Nuget package)。此包提供了原始 Linq 方法的替代方法,后者将字符串作为参数,并将这些字符串转换为适当的表达式。

例子:

async Task<int> GetIntColumn(int entityId, string intColumnName)
{
    return await TableRepository.Entities
        .Where(x => x.Id == entityId)
        .Select(intColumnName) // Dynamic Linq projection
        .Cast<int>()
        .SingleAsync();
}

我还把它变成了 async调用,因为现在所有的数据库调用都应该异步执行。当你调用这个方法时,你必须 await它得到结果(即:var res = await GetIntColumn(...);)。

通用变体

IQueryable 上将其更改为扩展方法可能更有用,并将列/属性类型变成泛型类型参数,这样您就可以将它与任何列/属性一起使用:

(前提是您的所有实体都有一个通用接口(interface),指定了 Id 属性。)

public static async Task<TColumn> GetColumn<TEntity, TColumn>(this IQueryable<TEntity> queryable, int entityId, string columnName)
    where TEntity : IEntity
{
    return await queryable
        .Where(x => x.Id == entityId)
        .Select(columnName) // Dynamic Linq projection
        .Cast<TColumn>()
        .SingleAsync();
}

它是这样调用的:var result = await TableRepository.Entities.GetColumn<Entity, int>(id, columnName);

接受列列表的通用变体

您可以进一步扩展它以支持动态选择多个列:

public static async Task<dynamic> GetColumns<TEntity>(this IQueryable<TEntity> queryable, int entityId, params string[] columnNames)
    where TEntity : IEntity
{
    return await queryable
        .Where(x => x.Id == entityId)
        .Select($"new({string.Join(", ", columnNames)})")
        .Cast<dynamic>()
        .SingleAsync();
}

它是这样调用的:var result = await TableRepository.Entities.GetColumns(id, columnName1, columnName2, ...); .

由于返回类型及其成员在编译时未知,我们必须返回 dynamic这里。这使得处理结果变得困难,但如果您只想将其序列化并将其发送回客户端,那么就可以了。

关于c# - 使用 Entity Framework 在运行时动态选择列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21084916/

相关文章:

c# - 格式化可变小数位数

c# - 确定 Clickonce 应用程序在 Clickonce 缓存中的位置

sql - Postgres - 观点是否得到准备好的陈述的支持?

sql - SQL 中的自定义排序

c# - 如何从 MVC3 中的编辑页面更新 View 模型?

c# - 如何在ajax回发后从代码隐藏调用javascript函数

javascript - 在javascript中通过id调用元素

c# - LINQ .FromSQL 错误 InvalidOperationException : Sequence contains more than one matching element

c# - 将 IEnumerable.Aggregate 与异步调用结合使用

sql - 如何解决此 SQL 代码中的 ORA-00918 错误