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()我已经用查询名称输入参数和内部查询对其进行了改进。:)再次感谢!