我有RESTful API,只处理下面的SQL Server数据库。API方法接受一个JSON字符串。这个字符串是EF实体的精确表示。想法是将字符串转换为实体并保存它。
下面的代码行[HttpPost]
public void ApiMethod([FromBody] string request)
{
var doc = JsonConverter.DeserializeObject<Document>(request);
_dbContext.Documents.Add(doc);
_dbContext.SaveChanges();
}
我想知道是否可以向外部客户端暴露实体结构?
另一种方法是
方法1:将json字符串转换为动态的,并通过映射属性来构建所需的实体。
[HttpPost]
public void ApiMethod([FromBody] string request)
{
dynamic anonymousDoc = JsonConverter.DeserializeObject(request);
var doc = new Document()
{
Property1 = anonymousDoc.Property1,
Property2 = anonymousDoc.Property2
}
_dbContext.Documents.Add(doc);
_dbContext.SaveChanges();
}
方法2:创建强类型DTO
[HttpPost]
public void ApiMethod([FromBody] string request)
{
var dto = JsonConverter.DeserializeObject<DocumentDTO>(request);
var doc = new Document()
{
Property1 = dto.Property1,
Property2 = dto.Property2
}
_dbContext.Documents.Add(doc);
_dbContext.SaveChanges();
}
然而,我必须在这里创建许多具有几乎相同属性的dto。
问题1:这里推荐的方法是什么?
问题2: (这个问题与问题1有关,所以我在这里发布它,而不是创建新的帖子)我上面提到的API是微服务架构的一部分。我有一堆通过HTTP相互通信的微服务。因为所有的服务都是相互解耦的,所以不存在强类型的数据契约。所以我认为传递JSON是一个好方法。我使用Newtonsoft.json
进行序列化/反序列化,因为它比microsoft的本机DataContractJsonSerializer具有更好的性能。这也是微服务之间通信的正确方法。
我想知道是否可以将实体结构暴露给外部客户吗?
通过直接跨服务边界公开实体结构,您在某种程度上几乎违反了SOA的每一个原则。
这些信条存在的原因是:保护你免受痛苦。这种方法可能给您带来的痛苦包括但不限于:
- 不能在不破坏消费者的情况下修改数据模型
- 将特定于数据存储实现的概念泄漏给消费者
- 服务层基本上是匿名的,缺乏任何业务定义
- 新的消费者没有办法知道如何消费服务
方法1:将json字符串转换为动态的,并构建所需的通过映射属性创建实体
根据您的确切需求,可能有您想要使用此方法的原因。例如,如果您所做的只是通过http公开基本上是数据库驱动程序的东西,那么这种方法可能很好。
然而,这实际上并没有解决任何痛点,因此与您最初的方法相似。
方法2:创建强类型DTO
这是一种更好的方法,但只是在一定程度上——它解决了上面提到的第一和第二痛点,但没有解决第三和第四痛点。我建议对这种方法进行调整,以解决以下问题:
方法3:创建强类型DTO并直接公开。
[HttpPost]
public void DoSomethingWithDocument([FromBody] DocumentDTO docDto)
{
// map from docDto to docEntity
...
_dbContext.Documents.Add(docEntity);
_dbContext.SaveChanges();
}
因为所有的服务都是相互解耦的,所以没有强类型数据契约。
试图通过拒绝共享契约来避免耦合是没有意义的。定义良好的契约是解耦服务的最佳方法之一。
我正在使用Newtonsoft。Json序列化/反序列化,因为它比微软的native性能更好DataContractJsonSerializer
如果您发现自己为了集成特定的工具或技术而完全偏离了常规的路径,那么我会非常小心。可能是不成熟的优化