[英]Unexpected behaviour with a multi-mapping query using Dapper.net
我才刚刚开始查看 Dapper.net,并且刚刚尝试了一些不同的查询,其中一个查询产生了我没想到的奇怪结果。
我有 2 个表 - Photos
& PhotoCategories
,其中与CategoryID
相关
照片表
PhotoId (PK - int)
CategoryId (FK - smallint)
UserId (int)
照片类别表
CategoryId (PK - smallint)
CategoryName (nvarchar(50))
我的 2 节课:
public class Photo
{
public int PhotoId { get; set; }
public short CategoryId { get; set; }
public int UserId { get; set; }
public PhotoCategory PhotoCategory { get; set; }
}
public class PhotoCategory
{
public short CategoryId { get; set; }
public string CategoryName { get; set; }
{
我想使用多重映射来返回Photo
的实例,以及相关PhotoCategory
的填充实例。
var sql = @"select p.*, c.* from Photos p inner
join PhotoCategories c
on p.CategoryID = c.CategoryID where p.PhotoID = @pid";
cn.Open();
var myPhoto = cn.Query<Photo, PhotoCategory, Photo>(sql,
(photo, photoCategory) => { photo.PhotoCategory = photoCategory;
return photo; },
new { pid = photoID }, null, true, splitOn: "CategoryID").Single();
执行此操作时,并非所有属性都被填充(尽管 DB 表和我的对象之间的名称相同。
我注意到如果我don't
“选择 p.* 等” 在我的SQL
中,而不是。
我明确 state 字段。
我想从查询中返回EXCLUDING
p.CategoryId
,然后所有内容都会被填充(显然 CategoryId 与我已从 select 语句中排除的照片 object 除外)。
但我希望能够在查询中包含该字段,并拥有它,以及在SQL
中查询的所有其他字段,以便填充。
我可以从我的Photo
class 中排除CategoryId
属性,并在需要 ID 时始终使用Photo.PhotoCategory.CategoryId
。
但在某些情况下,当我获得 Photo object 的实例时,我可能不想填充PhotoCategory
object。
有谁知道为什么会发生上述行为? 这对 Dapper 来说正常吗?
我刚刚对此进行了修复:
class Foo1
{
public int Id;
public int BarId { get; set; }
}
class Bar1
{
public int BarId;
public string Name { get; set; }
}
public void TestMultiMapperIsNotConfusedWithUnorderedCols()
{
var result = connection.Query<Foo1,Bar1,
Tuple<Foo1,Bar1>>(
"select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name",
(f,b) => Tuple.Create(f,b), splitOn: "BarId")
.First();
result.Item1.Id.IsEqualTo(1);
result.Item1.BarId.IsEqualTo(2);
result.Item2.BarId.IsEqualTo(3);
result.Item2.Name.IsEqualTo("a");
}
如果first
一种类型中有一个字段,那么多映射器会感到困惑,而second
类型也恰好是......并且......被用作分割点。
现在要克服 dapper 允许Id
字段显示在第一种类型的任何位置。 为了显示。
假设我们有:
classes: A{Id,FooId} B{FooId,Name} splitOn: "FooId" data: Id, FooId, FooId, Name
旧的拆分方法没有考虑它映射的实际底层类型。 所以...它映射了Id => A
和FooId, FooId, Name => B
新方法知道A
中的道具和字段。 当它第一次遇到FooId
中的 FooId 时,它不会开始拆分,因为它知道A
有一个名为FooId
的属性需要映射,下次它看到FooId
时它会拆分,从而产生预期的结果。
我知道这个问题很老,但我想我会用明显的答案为某人节省 2 分钟:只需从一张表中取一个 id 的别名:
IE:
SELECT
user.Name, user.Email, user.AddressId As id, address.*
FROM
User user
Join Address address
ON user.AddressId = address.AddressId
我有一个类似的问题。 这与子项和父项对于要拆分的字段具有相同名称的事实有关。 以下示例有效:
class Program
{
static void Main(string[] args)
{
var createSql = @"
create table #Users (UserId int, Name varchar(20))
create table #Posts (Id int, OwnerId int, Content varchar(20))
insert #Users values(99, 'Sam')
insert #Users values(2, 'I am')
insert #Posts values(1, 99, 'Sams Post1')
insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')
";
var sql =
@"select * from #Posts p
left join #Users u on u.UserId = p.OwnerId
Order by p.Id";
using (var connection = new SqlConnection(@"CONNECTION STRING HERE"))
{
connection.Open();
connection.Execute(createSql);
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }, splitOn: "UserId");
var apost = data.First();
apost.Content = apost.Content;
connection.Execute("drop table #Users drop table #Posts");
}
}
}
class User
{
public int UserId { get; set; }
public string Name { get; set; }
}
class Post
{
public int Id { get; set; }
public int OwnerId { get; set; }
public User Owner { get; set; }
public string Content { get; set; }
}
但以下不是因为在两个表和两个对象中都使用了“UserId”。
class Program
{
static void Main(string[] args)
{
var createSql = @"
create table #Users (UserId int, Name varchar(20))
create table #Posts (Id int, UserId int, Content varchar(20))
insert #Users values(99, 'Sam')
insert #Users values(2, 'I am')
insert #Posts values(1, 99, 'Sams Post1')
insert #Posts values(2, 99, 'Sams Post2')
insert #Posts values(3, null, 'no ones post')
";
var sql =
@"select * from #Posts p
left join #Users u on u.UserId = p.UserId
Order by p.Id";
using (var connection = new SqlConnection(@"CONNECTION STRING HERE"))
{
connection.Open();
connection.Execute(createSql);
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }, splitOn: "UserId");
var apost = data.First();
apost.Content = apost.Content;
connection.Execute("drop table #Users drop table #Posts");
}
}
}
class User
{
public int UserId { get; set; }
public string Name { get; set; }
}
class Post
{
public int Id { get; set; }
public int UserId { get; set; }
public User Owner { get; set; }
public string Content { get; set; }
}
在这种情况下,Dapper 的映射似乎变得非常混乱。 认为这描述了问题,但是我们可以采用解决方案/解决方法(除了 OO 设计决策)吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.