在dapper中使用一对多关系时出现splitOn错误
Posted
技术标签:
【中文标题】在dapper中使用一对多关系时出现splitOn错误【英文标题】:splitOn Error while using one to many relation in dapper 【发布时间】:2018-05-26 13:04:02 【问题描述】:我正在尝试使用 dapper 的 Multimapping 功能来返回 MenuCategories 和相关菜单的列表。但我收到以下错误:-
使用多映射 API 时,请确保设置 splitOn 参数,如果 您有除 Id 以外的密钥
这是我的课程:-
VMMenuCategory.cs
public class VMMenuCategory
public int MenuCategoryID get; set;
public string CategoryName get; set;
public System.DateTime CreatedOn get; set;
public DateTime? UpdatedOn get; set;
public List<VMMenu> Menus get; set;
VMMenus.cs
public class VMMenu
public int MenuID get; set;
public int MenuCategoryID get; set;
public string ProductName get; set;
public int? CostPrice get; set;
public int? SellingPrice get; set;
public System.DateTime CreatedOn get; set;
public DateTime? UpdatedOn get; set;
MenuCategoriesRepository.cs
public sealed class MenuCategoryRepository : Connection, IMenuCategoryRepository
List<VMMenuCategory> IMenuCategoryRepository.GetAllMenuCategories()
List<VMMenuCategory> _lstVMMenuCategory = new List<VMMenuCategory>();
string query = "select * from [dbo].[MenuCategories]";
using (var connection = GetConnection())
var data = connection.Query<VMMenuCategory, VMMenu, VMMenuCategory>(query, map:(mc,m) => mc.Menus =new List<VMMenu>() ;return mc; ,splitOn: "MenuID").ToList();
return data;
//return _lstVMMenuCategory;
【问题讨论】:
看起来[dbo].[MenuCategories]
表没有MenuID
列。
@DmitryEgorov,是的,它是一个子表。我试过splitOn: "MenuCategoryID"
,但我得到了同样的错误。
那么你需要在这个查询中加入两个表。
@DmitryEgorov,所以没有加入就没有办法做到这一点。作为实体框架在 ORM 中工作?
恐怕不行。 Dapper 不知道在哪里可以找到 VMMenu
的数据,除非您在查询中告诉它。
【参考方案1】:
为了使用来自两个表的数据填充两个对象,您必须查询这两个表。在您的情况下,它很可能是内部连接:
public sealed class MenuCategoryRepository : Connection, IMenuCategoryRepository
List<VMMenuCategory> IMenuCategoryRepository.GetAllMenuCategories()
List<VMMenuCategory> _lstVMMenuCategory = new List<VMMenuCategory>();
string query = @"
select mc.*, m.*
from [dbo].[MenuCategories] mc,
join [dbo].[Menus] m on mc.MenuCategoryID = m.MenuCategoryID
";
using (var connection = GetConnection())
var data = connection.Query<VMMenuCategory, VMMenu, VMMenuCategory>(
query,
map:(mc,m) =>
var foundMc = _lstVMMenuCategory
.FirstOrDefault(x => x.MenuCategoryID = mc.MenuCategoryID);
if (foundMc == null)
foundMc = mc;
foundMc.Menus = new List<VMMenu>() ;
foundMc.Menus.Add(m);
return mc;
,
splitOn: "MenuID").ToList();
return _lstVMMenuCategory;
注意:我猜到了第二个表名,并假设MenuID
在Menus
表定义中排在第一位。但是,最好在 select 子句中明确列出所有必需的列。
我还略微修改了映射器函数以避免类别集合中的重复。
【讨论】:
我已为您的答案投了票。感谢您节省了我的时间。你真是太棒了。 我没有得到想要的结果。我需要菜单类别下的菜单。基本上我需要分层数据。但我正在为每个菜单获取菜单类别。但我需要一个具有多个菜单的菜单类别。实际上,sql 查询的结果是相同的。【参考方案2】:为了填充分层数据,我更改了方法。
下面是代码:
public sealed class MenuCategoryRepository : Connection, IMenuCategoryRepository
List<VMMenuCategory> IMenuCategoryRepository.GetAllMenuCategories()
List<VMMenuCategory> _lstVMMenuCategory = new List<VMMenuCategory>();
string query = @"
select mc.*, m.*
from [dbo].[MenuCategories] mc
join [dbo].[Menu] m on mc.MenuCategoryID = m.MenuCategoryID";
using (var connection = GetConnection())
var vmMenuCategoryDictionary = new Dictionary<int, VMMenuCategory>();
var data = connection.Query<VMMenuCategory, VMMenu, VMMenuCategory>(
query,
map: (mc, m) =>
VMMenuCategory _VMMenuCategory;
if(!vmMenuCategoryDictionary.TryGetValue(mc.MenuCategoryID,out _VMMenuCategory))
_VMMenuCategory = mc;
_VMMenuCategory.Menus = new List<VMMenu>();
vmMenuCategoryDictionary.Add(_VMMenuCategory.MenuCategoryID, _VMMenuCategory);
_VMMenuCategory.Menus.Add(m);
return _VMMenuCategory;
,
splitOn: "MenuID").Distinct().ToList();
_lstVMMenuCategory = data;
return _lstVMMenuCategory;
【讨论】:
以上是关于在dapper中使用一对多关系时出现splitOn错误的主要内容,如果未能解决你的问题,请参考以下文章
Dapper - 多映射 API 确保您设置 splitOn
Dapper Multi-mapping APIs splitOn param Error - 我没有使用 MultiMapping