C#实体框架文本的SQL查询包装

C#实体框架文本的SQL查询包装

问题描述:

我有一个类似的问题: How to retrieve multiple columns from non-entity type sql query?C#实体框架文本的SQL查询包装

我需要实现方法string[,] DirectQuery(string sqlText, string[] param)这基本上是一个C#相当于SQL Server Management Studio中的。

用户应该输入的SQL查询作为文本串(+字符串参数,以避免SQL注入)和接收回包含该查询的结果的字符串矩阵。

在内部,我使用实体框架。

这里是我的实现:

public string[,] DirectQuery(string sqlQuery, string[] param) 
{ 
     //discover how many fields are specified in the select clause 
     string ip = sqlQuery.ToLower().Split(new string[] { "from" }, StringSplitOptions.None)[0]; 
     int cols = ip.Count(y => y == ',') + 1; 

     //execute the query 
     DbRawSqlQuery<string> res = param != null ? _context.Database.SqlQuery<string>(sqlQuery, param) : _context.Database.SqlQuery<string>(sqlQuery); 

     //wrap everything in a matrix to return 
     return res.ToArray().Array2Matrix(res.ToArray().Length /cols, cols); 
    } 

其中

public static T[,] Array2Matrix<T>(this T[] flat, int rows, int cols) where T : class 

是变成平坦的阵列到rows x cols矩阵我的自定义方法。

如果在select子句中用户指定了单个属性,那么工作正常,但在需要2+字段的情况下,执行DirectQuery会触发运行时异常dbrawsqlquery he data reader has more than one field. Multiple fields are not valid for EDM primitive or enumeration types。这是完全合理的,但由于查询可以是任何我不能创建自定义类来包装每一个可能的结果。

你有什么建议?

+1

如果你真的* *要允许用户输入原始的SQL查询,然后执行他们自己的名义,EF可能是*不*这个正确的工具。你应该看看像Dapper.NET(其中的权力这个网站,例如),很容易使原始的SQL的执行并打开结果变成漂亮的.NET对象与 –

+0

感谢很多工作,它工作得很好。但我仍然遇到一些与参数有关的问题。用户在查询中指定一定数量的参数,并按照他们的喜好命名(@ p0,@customerId,@ foo,...),并将其各自的值传递给字符串[]。如果我直接传递给查询方法,则Dapper会触发异常params string [];相反,它需要像'new {p0 =“17R13DT_GP_02_MP2”,...}“这样的结构。有没有更紧凑的方式来做到这一点? – jjhorn

问题是你正在使用一个方法 - DbRawSqlQuery,必须告诉它什么类型,你告诉它期望只是一个字符串,所以它不知道如何处理多个返回柱。

也许如果你指定string[]IEnumerable<string>或东西它的工作?或者,您可以定义一系列具有1,2,3,4等值的对象,并在运行时检测项目的数量并使用正确的类......但这看起来很荒唐。

真的不过,我建议不使用EF有人上文建议。找到可以返回动态对象的东西,或者直接使用ADO.Net。

+0

是否有可能使用Reflection创建具有1,2,3,4等值的运行时对象? – jjhorn

+0

可能吗?也许。但是通过在运行时创建类型,你只能在运行时访问属性,所以你基本上会丢掉任何编译时类型检查能力......你基本上创建的是一个数组/ list/table类型的东西,它使用反射来访问它的成员,所以毫无疑问,与仅仅使用数组相比,它是*非常低效的。我真的不想重新发明轮子 - 只要使用已经存在的类型并直接使用ADO.Net并使用DataTable即可。 – GPW