使用 Sql,如何从单个查询中合并子对象?
Using Sql, how can I hydrate child objects from within a single Query?
我正在使用 Dapper,但我认为这适用于一般情况 SQL:
我有以下内容:
var dapperQuery = "select * from ( select * from [User] where " +
"AccountDisabled <> 1 and " +
"Rate <= @maxRate and " +
"(datediff(day, Birthdate, @today) / 365) between @minage and @maxage";
// some conditional stuff
dapperQuery = dapperQuery + " order by LastOnline desc offset @skip rows fetch next 40 rows only ) As [Limit1] " +
"LEFT OUTER JOIN Photo AS [Extent2] ON [Limit1].[UserId] = [Extent2].[UserId]";
var dbProfiles = connection.Query<User>(dapperQuery, new {
maxRate = query.SearchMaxRate,
userPoint = "POINT (" + user.LocationLong + " " + user.LocationLat + ")",
searchRadius = radius,
today = DateTime.UtcNow,
minAge = query.SearchLowerAge,
maxAge = query.SearchUpperAge,
skip = query.Index * 40
}).ToList();
现在,这将返回我期望的结果,但 User.Photos
属性 始终为空。我如何从查询中对此进行补水?
我的用户 class:
[Table("User")]
public class User {
public User() {
Photos = new List<Photo>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Username { get; set; }
public DateTime Birthdate { get; set; }
[Index("LastOnlineIndex")]
public DateTime LastOnline { get; set; }
public string NumberConfirmationCode { get; set; }
public int Rate { get; set; }
public int SearchRadius { get; set; }
public int SearchLowerAge { get; set; }
public int SearchUpperAge { get; set; }
public int SearchMaxRate { get; set; }
public bool AccountDisabled { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
我的照片 class:
public class Photo {
public Photo() {}
[Key]
public int PhotoId { get; set; }
public string Url { get; set; }
public bool IsProfilePhoto { get; set; }
[ForeignKey("User")]
public int UserId { get; set; }
public virtual User User { get; set; }
}
public class PhotoConfiguration : EntityTypeConfiguration<Photo> {
public PhotoConfiguration() {
// One-to-Many
HasRequired(s => s.User).WithMany(s => s.Photos).HasForeignKey(s => s.UserId);
}
}
首先,如果您使用 Dapper.NET 获取实体,我不确定您为什么要发布 Entity Framework 流畅的配置。
如果要获取实体以及一对多相关实体,请查看 https://github.com/StackExchange/dapper-dot-net 上的 Dapper.NET 自述文件。本自述文件中的以下示例应该适用于您的情况:
var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id";
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});
考虑每个 User
都有一个集合 Posts
并且您想使用获取的关联来填充该集合。您可以使用 Linq to Objects 来实现这一点:
var users = data.GroupBy(p => p.Owner.Id).Select(g =>
{
var user = g.First().Owner;
user.Posts = g.ToList();
return user;
});
我正在使用 Dapper,但我认为这适用于一般情况 SQL:
我有以下内容:
var dapperQuery = "select * from ( select * from [User] where " +
"AccountDisabled <> 1 and " +
"Rate <= @maxRate and " +
"(datediff(day, Birthdate, @today) / 365) between @minage and @maxage";
// some conditional stuff
dapperQuery = dapperQuery + " order by LastOnline desc offset @skip rows fetch next 40 rows only ) As [Limit1] " +
"LEFT OUTER JOIN Photo AS [Extent2] ON [Limit1].[UserId] = [Extent2].[UserId]";
var dbProfiles = connection.Query<User>(dapperQuery, new {
maxRate = query.SearchMaxRate,
userPoint = "POINT (" + user.LocationLong + " " + user.LocationLat + ")",
searchRadius = radius,
today = DateTime.UtcNow,
minAge = query.SearchLowerAge,
maxAge = query.SearchUpperAge,
skip = query.Index * 40
}).ToList();
现在,这将返回我期望的结果,但 User.Photos
属性 始终为空。我如何从查询中对此进行补水?
我的用户 class:
[Table("User")]
public class User {
public User() {
Photos = new List<Photo>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Username { get; set; }
public DateTime Birthdate { get; set; }
[Index("LastOnlineIndex")]
public DateTime LastOnline { get; set; }
public string NumberConfirmationCode { get; set; }
public int Rate { get; set; }
public int SearchRadius { get; set; }
public int SearchLowerAge { get; set; }
public int SearchUpperAge { get; set; }
public int SearchMaxRate { get; set; }
public bool AccountDisabled { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
我的照片 class:
public class Photo {
public Photo() {}
[Key]
public int PhotoId { get; set; }
public string Url { get; set; }
public bool IsProfilePhoto { get; set; }
[ForeignKey("User")]
public int UserId { get; set; }
public virtual User User { get; set; }
}
public class PhotoConfiguration : EntityTypeConfiguration<Photo> {
public PhotoConfiguration() {
// One-to-Many
HasRequired(s => s.User).WithMany(s => s.Photos).HasForeignKey(s => s.UserId);
}
}
首先,如果您使用 Dapper.NET 获取实体,我不确定您为什么要发布 Entity Framework 流畅的配置。
如果要获取实体以及一对多相关实体,请查看 https://github.com/StackExchange/dapper-dot-net 上的 Dapper.NET 自述文件。本自述文件中的以下示例应该适用于您的情况:
var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id";
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});
考虑每个 User
都有一个集合 Posts
并且您想使用获取的关联来填充该集合。您可以使用 Linq to Objects 来实现这一点:
var users = data.GroupBy(p => p.Owner.Id).Select(g =>
{
var user = g.First().Owner;
user.Posts = g.ToList();
return user;
});