您缺少转换层。让我解释一下。
您存储在数据库中的帖子对象必须具有以下结构:
张贴表
+------------+----------------+-------+----------+
| PostId | ExternalPostId | Title | Content |
+------------+----------------+-------+----------+
- PostId - 这是您自己的表中的主键。自动生成,必填。
- ExternalPostId - 这是来自 API 的 PostId。
- 标题 - 这是来自 API 的标题
- 内容 - 这是来自 API 的内容。
标签表
+--------+---------------+-------------+-------------+
| TagId | ExternalTagId | OtherField1 | OtherField2 |
+--------+---------------+-------------+-------------+
- TagId - 这是您自己的 Tag 表的主键。自动生成,必填。
- ExternalTagId - 这是来自 API 的 TagId
- OtherField1、OtherField2 - 任何其他字段随 API 中的标记一起到达。
加入表格
+------------+-------+
| PostId | TagId |
+------------+-------+
- PostId、TagId - 复合主键
- PostId - 外键,必需,非自动编号,引用
Post 表。
- TagId - 外键,必需,非自动编号,引用
Tag 表。
此时您的实体将如下所示:
发布实体
[Table("Post")]
public class DbPost {
[Key]
[Column("PostId")]
public int Id { get; set; }
[Column("ExternalPostId")]
public int ExternalId { get; set; }
[Column("Title")]
public string Title { get; set; }
[Column("Content")]
public string Content { get; set; }
public IList<PostTag> PostTags { get; set; }
}
标签实体:
[Table("Tag")
public class DbTag
{
[Key]
[Column("TagId")]
public int Id { get; set; }
[Column("ExternalTagId")]
public string ExternalId { get; set; }
public IList<PostTag> PostTags { get; set; }
}
PostTag 实体
该实体保持不变。这里的区别是 PostId 映射到 Post 实体的 Id 属性,这是你自己的 Post 表的主键。以类似的方式,将 TagId 映射到 Tag 表的 Id 属性,这也是您自己的表的主键。
public class DbPostTag
{
public int PostId { get; set; }
public Post Post { get; set; }
public int TagId { get; set; }
public Tag Tag { get; set; }
}
最后,您的域上下文:
public class Database : DbContext {
public virtual DbSet<DbPost> Posts { get; set; }
public virtual DbSet<DbTag> Tags { get; set; }
public virtual DbSet<DbPostTag> PostTags { get; set; }
...
}
当您从 API 插入帖子时,您需要在来自 API 的帖子与数据库中的帖子实体之间创建翻译。您可以通过扩展方法或为您翻译它的方法来做到这一点:
public static class ApiObjectExtensions {
public static DbPost ToDbPost(this Post post){
var dbPost = new DbPost(){
ExternalId = post.PostId,
Title = post.Title,
Content = post.Content,
PostTags = new List<DbPostTags>()
};
}
public static DbTag ToDbTag(this Tag tag){
return new DbTag(){
ExternalId = tag.Id,
PostTags = new List<DbPostTags>()
};
}
}
因此,当您在域上下文中插入数据时,您只需转换相应的实体即可。这段代码假设你真的有上面描述的对象图,你的帖子有一堆帖子标签,每个帖子标签都有一堆标签。
foreach(var post in posts){
var dbPost = post.ToDbPost();
if(post.PostTags != null && post.PostTags.Any()){
foreach(var postTag in post.PostTags){
if(postTag.Tag != null){
var dbTag = postTag.Tag.ToDbTag();
var dbPostTag = new DbPostTag(){
Post = dbPost,
Tag = dbTag
};
dbPost.PostTags.Add(dbPostTag);
}
}
}
Database.DbPosts.Add(dbPost);
}
Database.SaveChanges();
如果您在单独的调用中接收帖子,帖子标签和标签与您的插入操作会有些不同:
var insertedPosts = new List<DbPost>();
var insertedTags = new List<DbTag>();
foreach(var post in posts){
var dbPost = post.ToDbPost();
Database.Posts.Add(dbPost);
insertedPosts.Add(dbPost);
}
foreach(var tag in tags){
var dbTag = tag.ToDbTag();
Database.Tags.Add(dbTag);
insertedTags.Add(dbTag);
}
Database.SaveChanges();
这会将所有 db post 和 db tag 实体写入 db 并分配它们的主键。
下一步是将两者联系在一起。
foreach(var postTag in postTags){
var dbPost = insertedPosts.FirstOrDefault(p => p.ExternalId = postTag.PostId);
var dbTag = insertedTags.FirstOrDefault(t => t.ExternalId = postTag.TagId);
if(dbPost != null && dbTag != null){
var dbPostTag = new DbPostTag(){
PostId = dbPost.Id,
Tag = dbTag.Id
};
Database.PostTags.Add(dbPostTag);
}
}
Database.SaveChanges();
最后一点是当您检索数据并希望它以原始格式显示时。
以下查询将返回所有帖子、它们的链接实体和它们的标签:
var dbPosts = this.Database.Posts
.Include( p => p.PostTags )
.ThenInclude(pt => pt.Tag )
.ToList();
var apiPosts = dbPosts.Select(p => p.ToApiPost()).ToList();
要将这些东西转换回原来的 Post、PostTag 和 Tag 类型,您可以简单地创建扩展方法,如下所示:
public static class DbObjectExtensions {
public static Post ToApiPost(this DbPost dbPost){
var post = new Post(){
PostId = dbPost.ExternalId,
Title = dbPost.Title,
Content = dbPost.Content,
PostTags = new List<PostTag>()
};
if(dbPost.PostTags != null) {
foreach(var dbPostTag in dbPost.PostTags){
if(dbPostTag.Tag != null){
var tag = dbPostTag.Tag.ToApiTag();
var postTag = new PostTag(){
PostId = post.PostId,
Post = post,
TagId = tag.TagId,
Tag = tag
};
post.PostTags.Add(postTag);
tag.PostTags.Add(postTag);
}
}
}
return post;
}
public static Tag ToApiTag(this DbTag dbTag){
return new Tag(){
TagId = dbTag.ExternalId
};
}
}