【问题标题】:Get value from c# anonymous Type using HierarchyId使用 HierarchyId 从 c# 匿名类型获取值
【发布时间】:2020-06-23 17:20:55
【问题描述】:

我正在尝试在 .net 中使用 SqlHierarchyId

在我的控制器中,我使用匿名类型从数据库中获取值。

[HttpGet("{id}")]
public async Task<ActionResult<object>> GetDomain(int id)
{
    object domain = from x in _context.Domains.Where(x => x.DomainId == id)
                 select new
                 {
                     Id = x.DomainId,
                     Name = x.DomainName,
                     Type = x.DomainTypeId,
                     Parent = x.Parentt,
                     Path = x.Level.ToString()
                 };
    return domain;
}

然后我想获取要转换为 SqlHierarchyId 的路径,以便应用 .Net 支持的不同方法

我尝试过反射:

System.Type type = domain.GetType();
string strNode = (string) type.GetProperty("Path").GetValue(domain, null);

我有这个错误:

System.NullReferenceException:对象引用未设置为实例 一个对象。

当我调试我的代码时,我发现 strNode 为空,但域包含我在使用 Postman 测试时需要的所有值。

我尝试动态:

dynamic dyn= domain;
string strNode= dyn.Path;

我有这个错误:

Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryablef__AnonymousType1>' 不包含“路径”的定义

我还尝试了在类似问题上找到的其他几个命题(克隆,将匿名类型定义为类...),但没有结果。

注意: 我正在尝试使用匿名类型,因为当直接使用我的模型时我无法获得值。我有一个像这样的铸造错误。

无法将“Microsoft.SqlServer.Types.SqlHierarchyId”类型的对象转换为“Microsoft.Data.SqlClient.Server.IBinarySerialize”类型。

但是通过匿名我可以获取这些值,所以我现在想访问这些值并将其传递给我的模型。

【问题讨论】:

  • 我得到“无法将 'Microsoft.SqlServer.Types.SqlHierarchyId' 类型的对象转换为类型 'Microsoft.Data.SqlClient.Server.IBinarySerialize'。”应用 Level.ToString() 时出错,我在 Level 的实体中使用 SqlHierachyId 类型,你也这样做吗?

标签: c# .net anonymous-types hierarchyid


【解决方案1】:

主要问题或假设是 GetDomain Action 的返回值。 Linq Where 返回集合(您应用此过滤器的类型),因此在这种情况下,域将保存匿名 IQueryable,而不是单个域。

如果要返回单个域,请使用FirstOrDefault,如下所示:

[HttpGet("{id}")]
public async Task<ActionResult<object>> GetDomain(int id)
{   
    object domain = (from x in _context.Domains.Where(x => x.DomainId == id)
                 select new
                 {
                     Id = x.DomainId,
                     Name = x.DomainName,
                     Type = x.DomainTypeId,
                     Parent = x.Parentt,
                     Path = x.Level.ToString()
                 }).FirstOrDefault();
    /*    
    // Or use FirstOrDefault in place of Where as shown below                
     object domain = (from x in _context.Domains
                 select new
                 {
                     Id = x.DomainId,
                     Name = x.DomainName,
                     Type = x.DomainTypeId,
                     Parent = x.Parentt,
                     Path = x.Level.ToString()
                 }).FirstOrDefault(x => x.Id == id);
    */
    return domain;
}

在此更改之后,您的其余代码应该可以按预期工作。

【讨论】:

    【解决方案2】:

    您的问题是domain 实际上是匿名对象的IEnumerable。即使只有一个实例,select 语句也会生成 IEnumerable

    如果你想得到实际的对象,那么你可以像这样抓取它。

    var obj = domain.FirstOrDefault();
    

    var obj = domain.Single();
    

    然后进行反射查找:

    var type = obj.GetType();
    var strNode = (string) type.GetProperty("Path").GetValue(obj, null);
    

    【讨论】:

    • 我以前直接在select子句后面加上FirstOrDefault()。当我在新语句中应用它时它不起作用。但这就是想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多