【问题标题】:Generic QueryMultiple with Dapper使用 Dapper 的通用 QueryMultiple
【发布时间】:2017-04-04 05:44:38
【问题描述】:

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

  public T Get<T>(Func<IDbConnection, T> query)
    {
        using (IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["myDB"].ConnectionString))
        {
            return 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();
}

是否有可能在我的 BaseRepository 中有一个 Generic GetMultiple 或者将 get multi 包装在我的 Get 方法中,然后在其中的汽车和选项有自己单独的 Get 调用?

【问题讨论】:

  • 随着您的用例变得越来越复杂,解决方案变得越来越不常用。我不建议将这样的东西放在 BaseRepository 类中。如果您打算这样做,您需要几个用例才能正确构建它。
  • 是的,我认为类似。在那一刻,我将该方法的实现分开而不是基本存储库,并认为它符合我的需求。干杯
  • 这段代码增加了什么价值?只是连接字符串的选择。并且它将整个 Dapper 表面简化为 Query 调用。这很聪明,但我认为这不是一个好主意。

标签: c# .net generics dapper


【解决方案1】:

你可以做这样的事情,它会返回一个包含你所追求的每种类型的 IEnumerables 的元组。

在基础存储库中

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

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;
        }

【讨论】:

  • 我会试一试的。实际上,我曾认为 usimg Tuple 是可行的方法,但是却被如何正确返回它所困扰。你会推荐什么命名两个通用类型?我以前在 pr T 和 TU 的书中看到过 T 和 U。猜猜 T1 和 T2 很好,或者只是想知道是否有标准约定
  • 我认为 dapper 的人使用 T1,T2...你可以用泛型重载最多 8 个,元组是限制。
  • 私有方法getMultiple 并没有真正限制您的结果数量。所有的重载都只是为您输入...但是私有方法正在获取一个读取器函数数组,并返回一个 IEnumerables 数组...所以它只是变成了一个铸造游戏。
猜你喜欢
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-03
相关资源
最近更新 更多