【发布时间】:2021-08-16 10:56:07
【问题描述】:
对于大多数查询,我正在尝试从 EntityFramework Core 转换为 Dapper。我有一个 sql 表(树结构)定义为:
[Table("bma_ec_categories")]
public class Category
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("category_id")]
public int CategoryId { get; set; }
[Column("parent_category_id")]
public int ParentId { get; set; }
[Required]
[Column("category_name")]
[StringLength(50)]
public string Name { get; set; }
public ICollection<Category> Children { get; set; }
[Column("title")]
[StringLength(150)]
public string Title { get; set; }
[Column("description")]
[StringLength(250)]
public string Description { get; set; }
[Column("keywords")]
[StringLength(250)]
public string Keywords { get; set; }
[Column("page_content", TypeName = "text")]
public string PageContent { get; set; }
[Column("banner_group_id")]
public int? BannerGroupId { get; set; }
[Column("inactive")]
public bool? Inactive { get; set; }
[Column("issitecategory")]
public bool Issitecategory { get; set; }
[Column("sort_order")]
public int? SortOrder { get; set; }
}
这是一个tree。我还有一个dto 定义为:
public class CategoryDto
{
[Key]
public int CategoryId { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Keywords { get; set; }
public string PageContent { get; set; }
public int? BannerGroupId { get; set; }
public bool? Inactive { get; set; }
public bool Issitecategory { get; set; }
public int? SortOrder { get; set; }
public ICollection<CategoryDto> Children { get; set; }
}
我的Item Service 有这个 Dapper 查询,大部分是我从 EF Core 复制的:
public IEnumerable<CategoryDto> GetCategoriesWithDapperUnbuffered()
{
var plainResult = _dapper.GetCategoriesUnbuffered();
var categoryDtos = plainResult.ToList();
var lookup = categoryDtos.Where(x => x.ParentId != 0).ToLookup(x => x.ParentId);
foreach (var c in categoryDtos)
{
if (lookup.Contains(c.CategoryId))
{
c.Children = lookup[c.CategoryId]
.OrderBy(x => x.SortOrder)
.ThenBy(x => x.Name)
.ToList();
}
}
var dto = categoryDtos
.Where(x => x.ParentId == 0)
.OrderBy(x => x.SortOrder)
.ThenBy(x => x.Name)
.ToList();
return dto;
}
...GetCategoriesUnbuffered 是:
public IEnumerable<CategoryDto> GetCategoriesUnbuffered()
{
string sql = "SELECT * FROM [dbo].[bma_ec_categories]";
using (DbConnection db = _connectionFactory.CreateConnection())
{
var categories = db.Query<CategoryDto>(sql, buffered: false).ToList();
return categories;
}
}
我还可以展示一个 Dapper Fluent 映射。这个查询确实有效。但我试图通过在原始查询中使用 Dapper 的多映射功能来进一步优化。这是我目前所拥有的:
public IEnumerable<CategoryDto> GetCategoriesMultiMapping()
{
string sql = "SELECT * FROM [dbo].[bma_ec_categories] AS [A] INNER JOIN [dbo].[bma_ec_categories] AS [B] ON [A].[category_id] = [B].[parent_category_id];";
using (DbConnection db = _connectionFactory.CreateConnection())
{
var categoryDictionary = new Dictionary<int, CategoryDto>();
var list = db.Query<CategoryDto, CategoryDto, CategoryDto>(
sql,
(category, children) =>
{
if (!categoryDictionary.TryGetValue(category.ParentId, out var categoryEntry))
{
categoryEntry = category;
categoryEntry.Children = new List<CategoryDto>();
categoryDictionary.Add(categoryEntry.ParentId, categoryEntry);
}
categoryEntry.Children.Add(children);
return categoryEntry;
},
splitOn: "category_id,category_id", buffered: false)
.Distinct()
.ToList();
return list;
}
}
这将返回第一个类别,并将所有其他类别作为其子类别。我在尝试splitOn category_id 的第二个实例时遇到了麻烦。我尝试改编 Dapper 的 Example - Query Multi-Mapping (One to Many) 中的一对多示例。任何帮助将不胜感激。
【问题讨论】:
-
我强烈建议您只指定您需要的列,并且不要在 Multi-map 查询中重复列
-
@Charlieface 你的意思是
SELECT * -
是的,明确指定列,参见sqlblog.org/2009/10/10/…
-
@Charlieface 谢谢,已在源代码中修复。你还说
do not duplicate columns,你建议我怎么做才能避免重复树中的列?
标签: c# sql-server tree dapper