C# 4.0 在委托、函数或操作C中概括简洁的查询#

C# 4.0 在委托、函数或操作C中概括简洁的查询#,c#-4.0,generics,dapper,C# 4.0,Generics,Dapper,我有几种类似下面这样的查询,结果有几种不同的类型。这是其中的一个具体示例,它生成例如列表: string anSql=GetSqlQueryText(“查询名称”); SqlConnection=GetSqlConnection(); 列表结果=空; 尝试 { connection.Open(); result=connection.Query(anSql,new//要从此处移动此部分吗 { param1=“value1”, param2=“value2” }).ToList();//到这里,到

我有几种类似下面这样的查询,结果有几种不同的类型。这是其中的一个具体示例,它生成例如列表:

string anSql=GetSqlQueryText(“查询名称”);
SqlConnection=GetSqlConnection();
列表结果=空;
尝试
{
connection.Open();
result=connection.Query(anSql,new//要从此处移动此部分吗
{
param1=“value1”,
param2=“value2”
}).ToList();//到这里,到外部调用
}
catch//省略了更多错误处理和重试逻辑,这是一个简化版本
{
result=new List();//这很好,可以由泛型类型填充
}
最后
{
connection.Close();
}
我想将此类查询加入GenDapperQuery泛型方法中,该方法可以在委托(或Func/Action或任何其他)的帮助下调用,类似于这样(在最终代码中T将是ClassA或ClassB等):

List result=GenDapperQuery(()=>
{
结果=connection.Query(anSql,新
{
param1=“value1”,
param2=“value2”
}).ToList();
}
//我想把结果作为一个特定的类型使用,比如ClassA
//要么立即,要么在演员表演之后
结果[0]。Id=3;//或
(结果作为列表)[0]。Id=3;
因此,我的目的是多次使用连接、错误处理/重试逻辑,当然还有Dapper查询(因为我不想写下我拥有的查询和类型),但我想对这个(想要的)泛型方法说,用Dapper查询什么以及什么类型的(泛型)创建并填写列表

(这个(想要的)泛型方法将在同一个类中,我可以在其中创建一次连接。错误处理部分将更加复杂,但在每种类型中都是相同的,这就是为什么我不想多次将它们写下来。参数可以自由变化,就像sql字符串作为输入一样。)

我现在的问题是,我无法围绕自己的代码编写一个通用的简洁查询,而是使用这个(想要的)方法之外的特定注入函数


这在C#中可能吗?任何建议都将不胜感激。

有许多方法可以实现这一点。一种机制是为Execute/ErrorHandler创建一个方法:

public TResult ExecuteWrapper<TResult>(SqlConnection connection, Func<TResult, SqlConnection> func)
{
    TResult result;
    try
    {
        connection.Open();
        // Query will be wrapped in a function or lambda
        result = func(connection);
    }
    catch //more error handling and retry logic omitted and this is a simplified version
    {
        // Specifying a new TResult may be more difficult. You could either:
        // 1. Pass a default value in the method parameter
        //    result = defaultValue; // defaultValue is method parameter
        // 2. Use System.Activator to create a default instance
        //    result = (TResult)System.Activator(typeof(TResult));

        // Original: result = new List<ClassA>(); // this good to be filled up by the generic type
    }
    finally
    {
        connection.Close();
    }
    return result;
}
public-TResult-ExecuteWrapper(SqlConnection-connection,Func-Func)
{
结果结果;
尝试
{
connection.Open();
//查询将包装在函数或lambda中
结果=func(连接);
}
catch//省略了更多错误处理和重试逻辑,这是一个简化版本
{
//指定新的TResult可能更困难。您可以:
//1.在方法参数中传递默认值
//结果=defaultValue;//defaultValue是方法参数
//2.使用System.Activator创建默认实例
//结果=(TResult)System.Activator(typeof(TResult));
//Original:result=new List();//这很好,可以由泛型类型填充
}
最后
{
connection.Close();
}
返回结果;
}
然后你会这样使用它:

List<ClassA> result = ExecuteWrapper(connection, (cn) =>
    {
        string anSql = GetSqlQueryText("query_name");
        return cn.Query<ClassA>(anSql, new
            {
                param1 = "value1",
                param2 = "value2"
            }).ToList();        
    });
List result=ExecuteWrapper(连接,(cn)=>
{
字符串anSql=GetSqlQueryText(“查询名称”);
返回cn.Query(anSql,新建
{
param1=“value1”,
param2=“value2”
}).ToList();
});

基于Ryan的好答案,我发布了我的改进,以将这些解决方案放在一起。此包装函数不仅请求SQL连接,还请求查询的名称。因此,此解决方案较短,调用端只有一行,可能更优雅。
修改后的包装器函数:

public TResult ExecuteWrapper<TResult>(SqlConnection connection, string queryName, Func<SqlConnection, string, TResult> func)
{
   string anSql = GetSqlText(queryName);
   TResult result;
   try
   {
      connection.Open();
      result = func(connection, anSql);
   }
   catch
   {
      result = System.Activator.CreateInstance<TResult>(); //this is working in .NET 4.5 environment
   }
   finally
   {
      connection.Close();
   }
   return result;
}
public-TResult-ExecuteWrapper(SqlConnection-connection,string-queryName,Func-Func)
{
字符串anSql=GetSqlText(queryName);
结果结果;
尝试
{
connection.Open();
结果=func(连接,anSql);
}
抓住
{
result=System.Activator.CreateInstance();//这在.NET 4.5环境中工作
}
最后
{
connection.Close();
}
返回结果;
}
而这个的主叫端:

List<ClassA> result = ExecuteWrapper(connection, "query_name", (conn, sql) =>
    {
        return conn.Query<ClassA>(sql, new
            {
                param1 = "value1",
                param2 = "value2"
            }).ToList();        
    });
List result=ExecuteWrapper(连接,“查询名称”,(conn,sql)=>
{
返回conn.Query(sql,新
{
param1=“value1”,
param2=“value2”
}).ToList();
});

再次感谢Ryan的回答。

干得好,谢谢!只是一个小错误,但它正在与我的更正一起工作(我已经对它进行了编辑并发送给您审阅)。我的编辑在ExecuteWrapper的标题中。对Func的正确/有效声明是:Func,所以这里的正确声明是:public TResult ExecuteWrapper(SqlConnection connection,Func Func)我的另一个改进是catch分支的一个工作示例:Activator.CreateInstance()我已经用查询名称输入参数和内部查询对其进行了改进。:)再次感谢!