【问题标题】:How can I retrieve JSON stored procedure's result with Entity Framework Core 2.0?如何使用 Entity Framework Core 2.0 检索 JSON 存储过程的结果?
【发布时间】:2019-04-30 05:00:04
【问题描述】:

Ciao, 我正在开发一个 Web API Core 2 项目,并且正在使用带有 SQL Azure 数据库的 Entity Framework Core 2。

其实

在 SQL Azure 数据库中,我有一个返回 JSON 的存储过程,如下所示:

CREATE PROCEDURE [dbo].[sp_Procedura]
AS
BEGIN

    SET NOCOUNT ON

    DECLARE @data NVARCHAR(MAX) = 
    (SELECT
        *
    FROM
        dbo.Entity
    FOR JSON AUTO)

    select 0 as 'Id', @data as 'data'
END

实际上,要读取结果,我必须创建一个实体来映射结果并使用以下代码读取数据:

string json = myContext
    .JsonResult.FromSql("exec dop.sp_Procedura")
    .ToList().FirstOrDefault().data;

在实体类下面:

public class Entity
{
    [Key]
    public int Id { get; set; }

    public string data { get; set; }
}

希望

我认为这个解决方案并不完全干净。我的存储过程应该是这样的:

CREATE PROCEDURE [dbo].[sp_Procedura]
AS
BEGIN

    SET NOCOUNT ON

    SELECT
        *
    FROM
        dbo.Entity
    FOR JSON AUTO
END

像以前一样有一个存储过程,使用 EF Core 2.0 有没有办法像下面的伪代码一样读取 JSON 结果?

string json = myContext.FromSql("exec dbo.sp_Procedura").Result;

谢谢你

【问题讨论】:

  • 您不需要 EF 来返回单个字符串。 Dapper 在这里是一个更好的选择。
  • 为什么还要在服务器上生成JSON?在使用 JSON.NET 的客户端上这样做更容易。只有当您有一个复杂的查询需要查询多个表并在客户端构建一个复杂的图形时,您才需要FOR JSON
  • Ciao,@PanagiotisKanavos 我同意你的观点,但出于内部政策,我不能使用 Dapper。关于您的第二条评论,我已经简化了场景,我需要使用 FOR JSON,因为我的存储过程构建了我的实体图。
  • 如果您不能使用 Dapper,请使用 DbContext 的连接使用普通的旧 SqlCommand。
  • 我喜欢这种解决方案,我不知道这种可能性。我会试试的。

标签: c# tsql entity-framework-core-2.1


【解决方案1】:

使用 newtonsoft.JSon nuget 包,您可以将实体转换为 JSON 并返回。不需要实现存储过程。

这种方式更快,因为实体框架可以使用二进制传输从SqlServer传输数据而不是整个字符串内容。

这里有一些 json 序列化的示例: https://www.newtonsoft.com/json/help/html/SerializeObject.htm

顺便说一下,我相信SqlServer里面也使用了newtonsoft.json。

【讨论】:

  • 并非总是如此。创建与FOR JSON 相同结果所需的对象图可能比简单地使用FOR JSON 执行查询更大更复杂。 FOR JSON AUTO 将从 JOIN 生成嵌套对象,其中仅包含每个表中选定的字段。使用 EF 时,必须使用返回与所需 JSON 文件形状相同的结果的查询,或者必须将这些结果转换为最终形式。
  • 不,SQL Server 不使用 Json.Net。
  • 你能给我真实的链接吗?所有 Microsoft 产品(包括 AzureBlob、CosmosDb)都使用 newtonsoft.json。而这个包是microsft官方的json supportet包
  • Not quite。请注意 JNK 本人对此的看法。仅仅因为公司一些部门中的一些产品和一些客户使用包并不意味着他们都这样做。
【解决方案2】:

您可以直接使用 SqlCommand 的 db 连接,即:

var entities = myContext.JsonQuery<List<Entity>>("sp_Procedure");

使用此扩展方法:

public static T JsonQuery<T>(this DbContext context, string query, params object[] parameters)
{
    using (var connection = context.Database.GetDbConnection())
    using (var command = connection.CreateCommand())
    {
        command.CommandText = query;
        command.Parameters.AddRange(parameters);
        connection.Open();
        return JsonConvert.DeserializeObject<T>((string)command.ExecuteScalar());
    }
}

【讨论】:

    猜你喜欢
    • 2018-04-25
    • 2018-08-13
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    相关资源
    最近更新 更多