pra*_*rab 7 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
}
Run Code Online (Sandbox Code Playgroud)
该表有四列存储整数值,我使用上面的函数分别读取它们.
现在我将其转换为Entity Framework.
public int sFunc(string sCol , int iId)
{
return Convert.ToInt32(TableRepository.Entities.Where(x => x.ID == iId).Select(x => sCol ).FirstOrDefault());
}
Run Code Online (Sandbox Code Playgroud)
但上面的函数返回错误
输入字符串格式不正确
因为它返回列名本身.
我不知道如何解决这个问题,因为我对EF很新.
任何帮助,将不胜感激
谢谢
8年后对OP来说不会有用,但这个问题有很多观点,所以我认为对其他人有一个正确的答案可能会有所帮助。
如果您使用实体框架,则应该执行 Linq 投影 ( Select()),因为这会导致在数据库端进行正确、高效的查询,而不是拉入整个实体。
不过,对于 Linq,Select()您通常必须提供 lambda,因此将列/属性名称放在字符串中是这里的主要困难。
最简单的解决方案是使用动态 LINQ(EntityFramework.DynamicLinq Nuget 包)。该包提供了原始 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();
}
Run Code Online (Sandbox Code Playgroud)
我也把它变成了一个async调用,因为现在所有的数据库调用都应该异步执行。当您调用此方法时,您必须通过await它来获取结果(即:)var res = await GetIntColumn(...);。
也许将其更改为 上的扩展方法IQueryable,并将列/属性类型设置为泛型类型参数更有用,这样您就可以将它与任何列/属性一起使用:
(假设您有一个用于指定属性的所有实体的通用接口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();
}
Run Code Online (Sandbox Code Playgroud)
这被称为这样: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();
}
Run Code Online (Sandbox Code Playgroud)
这被称为这样:var result = await TableRepository.Entities.GetColumns(id, columnName1, columnName2, ...);。
由于返回类型及其成员在编译时未知,因此我们必须dynamic在此处返回。这使得处理结果变得困难,但如果您只想序列化它并将其发送回客户端,那么就可以达到此目的。
这可能有助于解决您的问题:
public int sFunc(string sCol, int iId)
{
var _tableRepository = TableRepository.Entities.Where(x => x.ID == iId).Select(e => e).FirstOrDefault();
if (_tableRepository == null) return 0;
var _value = _tableRepository.GetType().GetProperties().Where(a => a.Name == sCol).Select(p => p.GetValue(_tableRepository, null)).FirstOrDefault();
return _value != null ? Convert.ToInt32(_value.ToString()) : 0;
}
Run Code Online (Sandbox Code Playgroud)
此方法现在适用于动态输入方法参数sCol。
更新:这不是当前问题的上下文,而是一般来说我们如何使用表达式选择动态列:
var parameter = Expression.Parameter(typeof(EntityTable));
var property = Expression.Property(parameter, "ColumnName");
//Replace string with type of ColumnName and entity table name.
var selector = Expression.Lambda<Func<EntityTable, string>>(property, parameter);
//Before using queryable you can include where clause with it. ToList can be avoided if need to build further query.
var result = queryable.Select(selector).ToList();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19366 次 |
| 最近记录: |