【问题标题】:NHibernate Query to json results are unexpectedNHibernate 查询到 json 结果是意外的
【发布时间】:2017-06-22 08:00:03
【问题描述】:

我正在使用 web api、angular 2 和 NHibernate 构建一个带有 .Net Core 的 web 应用程序。 我的数据库中有以下表格:

待办事项

ID
Name
Priority

优先级

ID
Name

这些表的映射如下:

[Class(NameType = typeof(Todo), Table = "Todo")]
public class Todo
{
    [ID(-2, Name = "ID")]
    [Generator(-1, Class = "native")]
    public virtual long ID { get; set; }

    [Property]
    public virtual string Name { get; set; }

    [ManyToOne]
    public virtual Priority Priority { get; set; }
}

[Class (NameType = typeof(Priority), Table = "Priority")]
public class Priority
{
    [ID(-2, Name = "ID")]
    [Generator(-1, Class = "native")]
    public virtual long ID { get; set; }

    [Property]
    public virtual string Name { get; set; }
}

我还有以下 DTO,我想创建一个列表并将其以 json 格式发送给客户端: 出于本示例的目的,我从中删除了一些其他属性。

public class TodoDTO
{
    public long ID { get; set; }

    public string Name { get; set; }

    public Priority Priority { get; set; }
}

当我运行下面的查询时:

var session = SessionFactoryConfigurationBase.GetSessionFactory().GetCurrentSession();

var query = session.QueryOver<Todo>();

TodoDTO todoSummary = null;

query.SelectList(list => list
    .Select(t => t.ID).WithAlias(() => todoSummary.ID)
    .Select(t => t.Name).WithAlias(() => todoSummary.Name)
    .Select(t => t.Priority).WithAlias(() => todoSummary.Priority))
.TransformUsing(Transformers.AliasToBean<TodoDTO>());

生成的 json 不显示 PriorityIDName 属性,但它显示以下内容:

[{
    "id":1,
    "name":"TEST",
    "priority":
    {
        "__interceptor":
        {
            "persistentClass":"Todo, ApplicationName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
            "identifier":2,
            "isUninitialized":true,
            "unwrap":false,
            "session":null,
            "entityName": "Priority",
            "isReadOnlySettingAvailable":false
        }
    }
}]

为什么它不显示IDName 属性,而是显示类定义? 当我从上面的查询中创建一个单独的列表时,我首先得到了我期望的结果,但这似乎相当麻烦。

---------- 编辑 -------------

根据要求,给出我期望的结果的代码:

public IList<Todo> GetTodos()
{
        var session = SessionFactoryConfigurationBase.GetSessionFactory().GetCurrentSession();

    var query = session.QueryOver<Todo>()
    .Fetch(t => t.Priority).Eager
    .List<Todo>();

    if(!query.Any())
    {
        return null;
    }

    var result = (
        from t in query
        select new TodoDTO
        {
            ID = t.ID,
            Name = t.Name,
            Priority = t.Priority
        }
    ).ToList();        

    return result;
}

结果返回给客户端,代码如下:

public JsonResult GetTodos()
{
    var todos = GetTodos();

    return new JsonResult(todos);
}

【问题讨论】:

  • 哪一行生成了 JSON?您能否向我们展示您编写的可行的替代方案?
  • 我不认为你已经通过对结果 query 使用 List() 方法来“实现”你的结果。
  • @David Osborne:我很确定这是问题所在,但我不知道如何准确解决。
  • 你能告诉我们为什么你不想使用你已经拥有的方式吗?
  • 多年来我一直在使用 Linq to SQL,因此我可以在查询本身中调整我的结果。使用 QueryOver,我需要更多代码来做同样的事情。我只是想确保我做得对。

标签: c# json nhibernate queryover


【解决方案1】:

这可能是实现您想要的更简洁的方法:

var todos = 
    session
        .Query<Todo>()
        .Fetch(t => t.Priority)
        .Select(t => 
            new {
               t.ID,
               t.Name,
               Priority = new {
                   t.Priority.Id,
                   t.Prioriry.Name}
            })
        .ToList();

return new JsonResult(todos);

我省略了 DTO 以证明它不是绝对必要的。但是,可以更改 Select() 调用以创建新的 DTO。

我只是想确保我做得对。

对于QueryOver()Query(),没有“正确的方法”。我发现Query() 通常更具可读性和整洁性,但有时缺乏我可能需要的控制。我通常从Query() 开始,如果我遇到困难或者我对Query() 生成的SQL 不满意,我会“升级”到QueryOver()

【讨论】:

    【解决方案2】:
    query.SelectList(list => list
        .Select(t => t.ID).WithAlias(() => todoSummary.ID)
        .Select(t => t.Name).WithAlias(() => todoSummary.Name)
        .Select(t => t.Priority).WithAlias(() => todoSummary.Priority))
    .TransformUsing(Transformers.AliasToBean<TodoDTO>());
    

    问题的可能原因是您没有将这行代码的结果分配给变量。

    [{
        "id":1,
        "name":"TEST",
        "priority":
        {
            "__interceptor":
            {
                "persistentClass":"Todo, ApplicationName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
                "identifier":2,
                "isUninitialized":true,
                "unwrap":false,
                "session":null,
                "entityName": "Priority",
                "isReadOnlySettingAvailable":false
            }
        }
    }]
    

    您收到上述 JSON 可能是因为您将 query 变量转换为 JSON,而不是 SelectList 调用的结果。

    【讨论】:

    • 好的,我可以理解,但那我该怎么做呢?
    • 根据以下文章,无法将实体填充到属性中:andrewwhitaker.com/blog/2014/06/19/…
    • “您不能填充完整的实体(例如,.Select(() => productReview.Product).WithAlias(() => result.Product))”在最后一个之前的段落中AliasToBean 部分
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    • 2019-05-04
    • 1970-01-01
    • 2023-03-05
    • 2010-11-25
    • 2020-09-17
    • 2016-09-10
    相关资源
    最近更新 更多