我有以下POCO:
[Alias("Posts")]
public class Post : IReturn<Post>
{
[AutoIncrement]
[PrimaryKey]
public int PostId { get; set; }
public DateTime CreatedDate { get; set; }
[StringLength(50)]
public string CreatedBy { get; set; }
[StringLength(75)]
public string Title { get; set; }
public string Body { get; set; }
public int UpVote { get; set; }
public int DownVote { get; set; }
public bool IsPublished { get; set; }
public List<Comment> Comments { get; set; }
public List<Tag> Tags { get; set; }
}
我的Comment
和Tag
个实体上有一个FK。所以我想从我的服务中回复我的回复,但它会说'Invalid Column name 'Comments''
和'Invalid Column name 'Tags''
。如何使用ORM Lite查看哪些评论和标签附加到我的帖子?在EF中,我只是使用Include来延迟加载我的相关表信息,等同于什么?
在回答答案时,我已经这样做了:
public class PostFull
{
public Post Post { get; set; }
public List<Comment> Comments { get; set; }
public List<Tag> Tags { get; set; }
}
然后在我的服务中,我返回此信息,我的实体PostTag
是一个交集实体,因为我的Post
和Tag
实体是M:M关系:
var posts = Db.Select<Post>().ToList();
var fullPosts = new List<PostFull>();
posts.ForEach(delegate(Post post)
{
var postTags = Db.Select<PostTag>(x => x.Where(y => y.PostId ==
post.PostId)).ToList();
fullPosts.Add(new PostFull()
{
Post = post,
Tags = Db.Select<Tag>(x => x.Where(y => postTags.Select(z =>
z.TagId).Contains(y.TagId))).ToList(),
Comments = Db.Select<Comment>(x => x.Where(y => y.PostId ==
post.PostId)).ToList()
});
});
return fullPosts;
不确定它是否是一个好的设计模式?
以下是我的实体:
[Alias("Tags")]
public class Tag
{
[AutoIncrement]
[PrimaryKey]
public int TagId { get; set; }
[StringLength(50)]
public string Name { get; set; }
}
[Alias("Posts")]
public class Post
{
[AutoIncrement]
[PrimaryKey]
public int PostId { get; set; }
public DateTime CreatedDate { get; set; }
[StringLength(50)]
public string CreatedBy { get; set; }
[StringLength(75)]
public string Title { get; set; }
public string Body { get; set; }
}
[Alias("PostTags")]
public class PostTag
{
[AutoIncrement]
[PrimaryKey]
public int PostTagId { get; set; }
[References(typeof(Post))]
public int PostId { get; set; }
[References(typeof(Tag))]
public int TagId { get; set; }
}
答案 0 :(得分:6)
OrmLite中的表格与基础数据库表格严格为 1:1映射。
这意味着所有复杂类型属性都是 blobbed 到具有属性名称的db文本字段中,它们从未用于自动映射到子关系,因为您希望在此处执行此操作。
这是一个早期答案,展示了你如何map many to many relations with OrmLite。
尽量避免 N + 1 查询,请记住每次调用Db.x
都是远程数据库查询,因此理想情况下应尽量避免循环中的任何数据库调用。
您可以使用OrmLite's support for JOINs构建类型化查询,就像在普通SQL中一样,通过“多对多”表查询并查找具有指定标记的所有帖子:
使用测试数据创建和填充帖子db.CreateTable<Post>();
db.CreateTable<Tag>();
db.CreateTable<PostTag>();
var post1Id = db.Insert(new Post {
CreatedBy = "gistlyn", Title = "Post 1", Body = "Body 1" }, selectIdentity:true);
var post2Id = db.Insert(new Post {
CreatedBy = "gistlyn", Title = "Post 2", Body = "Body 2" }, selectIdentity:true);
db.Insert(new Tag { Id = 1, Name = "A" },
new Tag { Id = 2, Name = "B" });
db.Insert(new PostTag { PostId = post1Id, TagId = 1 },
new PostTag { PostId = post1Id, TagId = 2 });
db.Insert(new PostTag { PostId = post2Id, TagId = 1 });
当遵循上面的OrmLite的正常命名约定时,OrmLite can infer the relationship between each table可以避免为每个查询指定JOIN表达式,例如:
var postsWithTagB = db.Select(db.From<Post>()
.Join<PostTag>()
.Join<PostTag,Tag>()
.Where<Tag>(x => x.Name == "B"));
postsWithTagB.PrintDump();
此查询仅返回标记B
的第一个帖子以及标记A
的两个帖子。
您可以通过running it Live on Gistlyn在线进一步探索这个独立的示例。
如果这是一个小博客,您想加载所有帖子及其相关标签和评论,例如在主页或RSS源中,您可以使用Linq2Objects将整个数据集加载到内存中,并使用以下内容将它们连接起来:
//Only 4 DB calls to read all table data
var posts = Db.Select<Post>();
var postTags = Db.Select<PostTag>();
var tags = Db.Select<Tag>();
var comments = Db.Select<Comment>();
//using Linq2Objects to stitch the data together
var fullPosts = posts.ConvertAll(post =>
{
var postTagIds = postTags
.Where(x => x.PostId == post.PostId)
.Select(x => x.PostTagId).ToList();
return new PostFull {
Post = post,
Tags = tags.Where(x => postTagIds.Contains(x.TagId)).ToList(),
Comments = comments.Where(x => x.PostId == post.PostId).ToList(),
};
});
答案 1 :(得分:2)
您不必在Post实体中包含标签和评论。在您的情况下,您的DTO和DB模型类应该是不同的。在Tag和Comment类中,您应该具有PostId属性。
在服务中,您应查询其中PostId等于您的帖子ID的评论,并对标签执行相同操作。结果应添加到包含评论和标签列表的Post DTO中。