public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
public string UrlSlug { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string UrlSlug { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string UrlSlug { get; set; }
public string TnImage { get; set; }
public string Author { get; set; }
public List<Tag> Tags { get; set; }
public Category Category { get; set; }
public string DatePublished { get; set; }
public string DateCreated { get; set; }
public string DateModified { get; set; }
public string Description { get; set; }
public string ArticleBody { get; set; }
}
我正在使用针对Sql Server Compact嵌入式数据库的Entity-Framework,并编写了一个通用存储库,它针对Post
,Category
等单个实体执行CRUD操作,Tag
等。
一切正常。
我正在编写ASP.Net Web API以通过REST-ful API公开CRUD。
╔═══════╦═══════════════════════╦════════════════════════════════════╗
║ VERB ║ End Point ║ Description ║
╠═══════╬═══════════════════════╬════════════════════════════════════╣
║ GET ║ /api/tags ║ Returns all Tags ║
║ GET ║ /api/tags/tips ║ Returns single Tag (name=tips) ║
║ POST ║ /api/tags ║ Creates new Tag ║
║ GET ║ /api/categories ║ Returns all Categories ║
║ GET ║ /api/categories/news ║ Returns single Category (name=news)║
║ POST ║ /api/categories ║ Creates new Category ║
║ GET ║ /api/posts ║ Returns all Post ║
║ GET ║ /api/posts/51 ║ Returns single Post (Id=51) ║
║ GET ║ /api/posts/2/Tags ║ Returns Tags for Post w/ Id=2 ║
║ GET ║ /api/posts/2/Category ║ Returns Category for Post w/ Id=2 ║
║ POST ║ /api/posts ║ Creates new Post ║
╚═══════╩═══════════════════════╩════════════════════════════════════╝
当我通过针对Post
端点执行POST
请求创建/api/posts
实体并且我将正文中的Post
实体数据作为JSON时,它可能会拥有1
个或更多标记实例以及0
或1
类别。
POST
博客文章正文{
"title": "How to get 6 Pack Abs in 6 days",
"urlSlug": "6-pack-abs-6-days",
"tnImage": "http:\/\/example.com\/image.jpg",
"author": "John Doe",
"tags": [
{
"name": "6 pack abs tips"
},
{
"name": "exercise tips"
},
{
"name": "workout videos"
}
],
"category": {
"name": "fitness"
},
"datePublished": "2017-04-01",
"dateCreated": "2015-01-20",
"dateModified": "2017-04-01",
"description": "SEO keyword stuffed description for fake tips to get abs here",
"articleBody": "full post body containing fake tips to get 6 packs. html"
}
在这些标签中,有些可能存在,有些可能不存在。需要创建不存在的那些。对于需要创建的标记,将使用辅助方法生成UrlSlug
。
如果类别已填写,则应插入该类别(如果不存在)。
考虑到这种情况,我如何针对POST
端点发出/api/posts
请求,并确保相关的Tag
和Category
实体在添加时添加存在吗?
如果上面显示的示例帖子发布到此端点,如何处理添加不存在的标记,如果不存在,则添加类别,然后添加新帖子?
另外,我在REST设计方面是否接近这个错误?如果是,建议的方法是什么,以确保数据不一致,即添加了一些标签,然后发生错误,所以现在有孤儿。
public class PostsController : ApiController
{
[Route("api/posts")]
[HttpPost]
public IHttpActionResult Post([FromBody]PostDto post)
{
try
{
if (post == null)
{
return BadRequest();
}
// what goes in here, so that I add tags that don't exist,
// category if it doesn't exist
// and then create the post. All ADD methods will call repo methods
//
// Also is there some other way, i.e. am I approaching this wrong?
}
catch (Exception)
{
return InternalServerError();
}
}
答案 0 :(得分:1)
我过去做过类似的事情,我做的就是数据库。当调用像“SetTag”这样的通用过程时,它将采用entityid和标签,然后首先执行检查查询,如:
DECLARE @TagID INT
SELECT @TagID = TagID FROM TagTable WHERE Tag = @TagPassedIn
IF @TagID IS NULL
BEGIN
INSERT INTO TagTable (Tag) VALUES (@TagPassedIn)
SELECT @TagID = SCOPE_INDENTITY()
END
INSERT INTO AttTable (EntityID,TagID) VALUES (@EntityIDPassedIn,@TagID)
答案 1 :(得分:1)
示例解决方案可以在这里:
using (var context = new YourContext())
{
//Find or Create Category
Category category = null;
if (context.Categories.Any(cat => cat.Name == post.category.Name))
{
category = context.Categories.FirstOrDefault(cat => cat.Name == post.category.Name);
}
else
{
category = new Category
{
Name = post.category.Name
};
context.Categories.Add(category);
}
//Find or Create Tags
var tags = new List<Tag>();
foreach (var tag in post.tags)
{
Tag targetedTag;
if (context.Tags.Any(t => t.Name == tag.Name))
{
targetedTag = context.Tags.FirstOrDefault(t => t.Name == tag.Name);
}
else
{
targetedTag = new Tag
{
Name = tag.Name,
// UrlSlug = use helper as you've said
};
context.Tags.Add(targetedTag);
}
tags.Add(targetedTag);
}
var targetedPost = new Post
{
Category = category,
Tags = tags,
ArticleBody = post.articleBody,
Author = post.author,
DateCreated = post.dateCreated,
DateModified = post.dateModified,
DatePublished = post.datePublished,
Description = post.description,
Title = post.title,
TnImage = post.tnImage,
UrlSlug = post.urlSlug
};
context.Posts.Add(targetedPost);
context.SaveChanges();
}