使用 HierarchyId 从 c# 匿名类型获取值

Get value from c# anonymous Type using HierarchyId

我正在尝试在 .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: Object reference not set to an instance of an object.

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

我试试动态的:

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

我有这个错误:

Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable<<>f__AnonymousType1>' does not contain a definition for 'Path

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

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

Unable to cast object of type 'Microsoft.SqlServer.Types.SqlHierarchyId' to type 'Microsoft.Data.SqlClient.Server.IBinarySerialize'.

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

您的问题是 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);

主要问题或假设与 GetDomain 操作中的 return 值有关。 Linq Where returns 集合(您正在应用此过滤器的类型),因此在这种情况下,域将持有匿名 IQueryable,而不是单个域。

如果你想return单域名,那么请使用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;
}

此更改后,您的其余代码应按预期工作。