C# 带短小的通用QueryMultiple

C# 带短小的通用QueryMultiple,c#,.net,generics,dapper,C#,.net,Generics,Dapper,我有一个基本的存储库,它有一个通用的Get方法,可以像Dapper一样返回数据 public T Get<T>(Func<IDbConnection, T> query) { using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString)) { retu

我有一个基本的存储库,它有一个通用的Get方法,可以像Dapper一样返回数据

  public T Get<T>(Func<IDbConnection, T> query)
    {
        using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
        {
            return query.Invoke(db);
        }
    }
publictget(Func查询)
{
使用(IDbConnection db=new SqlConnection(ConfigurationManager.ConnectionString[“myDB”].ConnectionString))
{
返回query.Invoke(db);
}
}
但是,我现在需要返回多个数据。DAL查询如下:

var multi = db.QueryMultiple(getCarDataSp , new { CustomerID = customerId, Year = year },
                                commandType: CommandType.StoredProcedure));

var cars = multi.Read<CarDTO>();
var options = multi.Read<CarOptionDTO>();

//wire the options to the cars
foreach(var car in cars){
    var carOptions = options.Where(w=>w.Car.CarID == car.CarID);        //I would override Equals in general so you can write w.Car.Equals(car)...do this on a common DataModel class
    car.Options = carOptions.ToList();
}
var multi=db.QueryMultiple(getCarDataSp,new{CustomerID=CustomerID,Year=Year},
commandType:commandType.StoredProcess);
var cars=multi.Read();
var options=multi.Read();
//将选项连接到汽车上
foreach(车辆中的var车辆){
var carOptions=options.Where(w=>w.Car.CarID==Car.CarID);//我通常会重写Equals,这样您就可以编写w.Car.Equals(Car)
car.Options=carOptions.ToList();
}

是否可能在我的BaseRepository中有一个通用的GetMultiple,或者是在我的get方法中包装get Multiple,然后在它们各自的get调用中包含cars和options?

您可以这样做,返回一个元组,其中包含您所追求的每种类型的IEnumerables

在基本存储库中

(基本上是一堆重载……如果有更多类型,可以添加更多重载)

公共元组GetMultiple(字符串sql、对象参数、, Func func1, Func func2) { var objs=getMultiple(sql、参数、func1、func2); 返回Tuple.Create(objs[0]作为IEnumerable,objs[1]作为IEnumerable); } 公共元组GetMultiple(字符串sql、对象参数、, Func func1, Func func2, Func func3) { var objs=getMultiple(sql,参数,func1,func2,func3); 返回Tuple.Create(objs[0]作为IEnumerable,objs[1]作为IEnumerable,objs[2]作为IEnumerable); } 私有列表getMultiple(字符串sql、对象参数、参数Func[]readerFuncs) { var returnResults=新列表(); 使用(IDbConnection db=new SqlConnection(ConfigurationManager.ConnectionString[“myDB”].ConnectionString)) { var gridReader=db.QueryMultiple(sql,参数); foreach(readerFunc中的变量readerFunc) { var obj=readerFunc(gridReader); 返回结果。添加(obj); } } 返回结果; } 在派生存储库中

(非常干净,更重要的是,打字!)

公共类Foo{}
公共类Bar{}
公开作废样本()
{
var sql=“从Foo中选择*select;从Bar中选择*select”;
var foosandbar=this.GetMultiple(sql,new{param=“baz”},gr=>gr.Read(),gr=>gr.Read());
var foos=foosandbar.Item1;
变量条=foosandbar.Item2;
}

您可以执行类似的操作,返回一个元组,其中包含您要查找的每种类型的IEnumerables

在基本存储库中

(基本上是一堆重载……如果有更多类型,可以添加更多重载)

公共元组GetMultiple(字符串sql、对象参数、, Func func1, Func func2) { var objs=getMultiple(sql、参数、func1、func2); 返回Tuple.Create(objs[0]作为IEnumerable,objs[1]作为IEnumerable); } 公共元组GetMultiple(字符串sql、对象参数、, Func func1, Func func2, Func func3) { var objs=getMultiple(sql,参数,func1,func2,func3); 返回Tuple.Create(objs[0]作为IEnumerable,objs[1]作为IEnumerable,objs[2]作为IEnumerable); } 私有列表getMultiple(字符串sql、对象参数、参数Func[]readerFuncs) { var returnResults=新列表(); 使用(IDbConnection db=new SqlConnection(ConfigurationManager.ConnectionString[“myDB”].ConnectionString)) { var gridReader=db.QueryMultiple(sql,参数); foreach(readerFunc中的变量readerFunc) { var obj=readerFunc(gridReader); 返回结果。添加(obj); } } 返回结果; } 在派生存储库中

(非常干净,更重要的是,打字!)

公共类Foo{}
公共类Bar{}
公开作废样本()
{
var sql=“从Foo中选择*select;从Bar中选择*select”;
var foosandbar=this.GetMultiple(sql,new{param=“baz”},gr=>gr.Read(),gr=>gr.Read());
var foos=foosandbar.Item1;
变量条=foosandbar.Item2;
}

随着您的用例变得越来越复杂,解决方案的通用性越来越差。我不建议在BaseRepository类中放置类似的内容。如果你打算这样做,你需要几个用例来正确地构建它。是的,我也这么认为。目前,我已将该方法的实现分开,而不是将其放在基础存储库中,并认为它适合我的需要。干杯这个代码增加了什么值?只是连接字符串的选择。它将整个简洁的表面简化为一个查询调用。这很聪明,但我认为这不是一个好主意。随着用例变得越来越复杂,解决方案变得越来越不通用。我不建议放点东西
public Tuple<IEnumerable<T1>, IEnumerable<T2>> GetMultiple<T1, T2>(string sql, object parameters,
                                        Func<GridReader, IEnumerable<T1>> func1,
                                        Func<GridReader, IEnumerable<T2>> func2)
        {
            var objs = getMultiple(sql, parameters, func1, func2);
            return Tuple.Create(objs[0] as IEnumerable<T1>, objs[1] as IEnumerable<T2>);
        }

        public Tuple<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>> GetMultiple<T1, T2, T3>(string sql, object parameters,
                                        Func<GridReader, IEnumerable<T1>> func1,
                                        Func<GridReader, IEnumerable<T2>> func2,
                                        Func<GridReader, IEnumerable<T3>> func3)
        {
            var objs = getMultiple(sql, parameters, func1, func2, func3);
            return Tuple.Create(objs[0] as IEnumerable<T1>, objs[1] as IEnumerable<T2>, objs[2] as IEnumerable<T3>);
        }

        private List<object> getMultiple(string sql, object parameters,params Func<GridReader,object>[] readerFuncs )
        {
            var returnResults = new List<object>();
            using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
            {
                var gridReader = db.QueryMultiple(sql, parameters);

                foreach(var readerFunc in readerFuncs)
                {
                    var obj = readerFunc(gridReader);
                    returnResults.Add(obj);
                }
            }

            return returnResults;
        }
public class Foo { }

        public class Bar { }

        public void sample()
        {
            var sql = "select * from Foo; select * from Bar";
            var foosAndBars = this.GetMultiple(sql, new { param = "baz" }, gr => gr.Read<Foo>(), gr => gr.Read<Bar>());
            var foos = foosAndBars.Item1;
            var bars = foosAndBars.Item2;
        }