Dapper.Query <KeyValueType <T1,T2 >>返回Null的集合

简单问题(已编辑:首先显示容易复制的示例,然后显示详细方案)

具有以下课程:

public class SalesMetrics {
   public decimal SalesDollars { get; set; }
   public decimal SalesUnits { get; set; }
}

public class ProductGroup {
   public string ProductId { get; set; }
   public string ProductName { get; set; }
}

使用以下Dapper查询,我的结果等于[{Key = null,Value = null}]

IEnumerable<keyvaluepair<ProductGroup,SalesMetrics>> result = sqlConnection
   .Query<keyvaluepair<ProductGroup,SalesMetrics>>(
       sql: @"SELECT 
                  1 As ProductId,'Test' AS ProductName,1.00 As SalesDollars,1 As SalesUnits");

我想知道Dapper是否可以将keyvaluepair作为输出类型处理,是这样的:查询的方式如何?


完整场景(为什么我需要这样做)

我正在创建一个“销售查询”构建器函数,该函数可以按不同的分组谓词对我的销售结果进行分组,并应基于该谓词type返回不同的结果类型。

我正在使用Dapper nuget包从SQL-Server获取结果。我正在idbconnection上使用Dapper.Query<T>()扩展方法

基本上,无论分组类型如何,我都想返回sum的SalesDollars和SalesUnits。对于输出的这一部分,我创建了以下类SalesMetrics

我希望我的Sales Query函数接受名为ProductGroup的Group类(generic parameter或任何其他类...)作为TGroup,该函数应返回{ {1}}

数据源

这是我的销售表keyvaluepair<TGroup,SalesMetric>

的布局
flatSales

我遇到问题的地方

我具有以下查询数据库的功能。

CREATE TABLE dbo.flatSales (
   SalesDate DATE NOT NULL,ProductId INT NOT NULL,ProductName VARCHAR(100) NOT NULL,ProductCategoryId INT NOT NULL,ProductCategoryName VARCHAR(100) NOT NULL,CustomerGroupId INT NOT NULL,CustomerGroupName VARCHAR(100) NOT NULL,CustomerId INT NOT NULL,CustomerName VARCHAR(100) NOT NULL,SalesUnits INT NOT NULL,SalesDollars INT NOT NULL
)

NULL的收集

代码public static IEnumerable<keyvaluepair<TGroup,SalesMetrics>> SalesTotalsCompute<TGroup>(System.Data.idbconnection connection) { string[] groupByColumnNames = typeof(TGroup) .GetProperties(bindingAttr: System.Reflection.Bindingflags.Public | System.Reflection.Bindingflags.Instance) .Select(x => x.Name) .ToArray(); string joinedGroupByColumnsnames = string.Join(",",groupByColumnNames); return connection.Query<keyvaluepair<TGroup,SalesMetrics>>(sql: $@" SELECT SUM(SalesDollars) AS SalesDollars,SUM(SalesUnits) AS SalesUnits,{joinedGroupByColumnsnames} FROM dbo.flatSales GROUP BY {joinedGroupByColumnsnames} "); } ,但返回一个keyvaluepair列表,其中Key和Value均为does not fail

我尝试对NULL之类的列进行别名设置,但是它并没有改变任何内容(也没有失败)...

ProductName as [Key.ProductName]生成的Sql查询如下(均返回空的keyvaluepair):

ProductGroup

有什么想法吗?

yoyo520621 回答:Dapper.Query <KeyValueType <T1,T2 >>返回Null的集合

我怀疑Dapper是否支持开箱即用的复杂对象。

也许您可以从Dapper的multi-mapping feature中受益:

NoMethodError:         NoMethodError: undefined method `Beluga' for nil:NilClass

备注

  • 我已经对列进行了重新排序,因为splitOn需要将两个对象分开的列的名称,否则,您将不得不传递AnimalVerifier数组中的第一项,这会更加随机
  • 如果您使用的是.NET Standard,请考虑返回ValueTuple,而不是public static IEnumerable<KeyValuePair<TGroup,SalesMetrics>> SalesTotalsCompute<TGroup>(System.Data.IDbConnection connection) { string joinedGroupByColumnsNames = string.Join(",",GetCachedColumnNamesFor<TGroup>()); return connection.Query<TGroup,SalesMetrics,KeyValuePair<TGroup,SalesMetrics>>( sql: $@"SELECT {joinedGroupByColumnsNames},SUM(SalesDollars) AS SalesDollars,SUM(SalesUnits) AS SalesUnits FROM dbo.FlatSales GROUP BY {joinedGroupByColumnsNames}",map: (groupData,salesMetricsData) => new KeyValuePair<TGroup,SalesMetrics>(groupData,salesMetricsData),splitOn: "SalesDollars"); }
  • 不要对每个调用都使用反射,我建议添加一个方法joinedGroupByColumnsNames,该方法仅使用静态ConcurrentDictionary调用ConcurrentDictionary.GetOrAdd方法,进行一次反射。

其他方法

您还可以让KeyValuePairGetCachedColumnNamesFor继承(或创建ProductGroup接口并让SalesMetrics实现该接口)并执行ISalesMetrics。另一个好处是编译器将阻止两个模型中的重复字段。

生成的方法将如下所示:

ProductGroup

这里的Query<ProductGroup>(...)方法反映了public static IEnumerable<TSalesData> SalesTotalsCompute<TSalesData>(System.Data.IDbConnection connection) where TSalesData : ISalesMetric { string joinedGroupByColumnsNames = string.Join(",GetCachedNonSalesMetricColumnNamesFor<TSalesData>()); return connection.Query<TSalesData>(sql: $@" SELECT SUM(SalesDollars) AS SalesDollars,SUM(SalesUnits) AS SalesUnits,{joinedGroupByColumnsNames} FROM dbo.FlatSales GROUP BY {joinedGroupByColumnsNames} "); } 中的属性,不包括GetCachedNonSalesMetricColumnNamesFor接口中的属性,再次缓存了结果。

本文链接:https://www.f2er.com/3151188.html

大家都在问