在 Linq 中将类转换为同一类的部分

本文关键字:一类 Linq 转换 | 更新日期: 2023-09-27 17:56:06

我在EF中作为实体的类是:

Cat { Id, ParentId, Name, ImageUrl, ...}
Tree { Id , ParentId, Name}

是否有其他选择:

var trees= (from rs in _db.ItemCats
            where rs.ParentId == null
            select new Tree
            {
                Id = rs.Id,
                ParentId = rs.ParentId,
                Name = rs.Name
            }).ToList();

像这样:

var trees= (from rs in _db.ItemCats
            where rs.ParentId == null
            select new 
            { 
                rs.Id, rs.Name, 
                rs.ParentId 
            }).Cast<Tree>().ToList();

但得到:

无法将类型"匿名类型"转换为类型"Meha3.Models.Tree"。 LINQ to 实体仅支持强制转换 EDM 基元或枚举 类型

在 Linq 中将类转换为同一类的部分

您要求的是"鸭子"类型,而 .Net 不支持"鸭子"类型,因此您无法直接强制转换它。 您的所有选项都包括通过映射、树上的构造函数、反射等将其转换为您想要的类型,但实际的强制转换是不可能的。

为指向其他 SO 答案的链接道歉,但我认为没有必要在这里复制详细信息......

转换选项在这里

此处为反射选项

斯基特的另一种方式,他特别说是可怕的......不要这样做...

我强烈建议使用转换方法或构造函数方法。

是的,有。但是,不像你的例子。您可能想查看自动映射器:

如果您使用它,您的问题将像这样解决:

Mapper.CreateMap<Cat, Tree>();
var tree = Mapper.Map<Tree>(cat);

不能从匿名类型强制转换为 Tree 类,因为匿名类型不属于树类型

您还违反了有关服务器端可以执行和不能执行的内容的各种 EF 规则

当我不得不执行类似的任务时,我最终不得不编写这样的代码 - 不优雅,但它有效:

var trees= (from rs in _db.ItemCats
        where rs.ParentId == null
        select new 
        { 
            Id = rs.Id, 
            Name = rs.Name, 
            ParentId = rs.ParentId 
        })
        .AsEnumerable() //to run the query and take us out of the EF domain
        .Select(a => new Tree()
        {
           Id = a.Id,
           Name = a.Name,
           ParentId = a.ParentId
        })
        .ToList();

你可以使用Lambada语法缩短一点,但不会缩短太多

像这样:

var trees= _db.ItemCats.Select(Cat => new Tree(){
            Id = Cat.Id,
            ParentId = Cat.ParentId,
            Name = Cat.Name
        }).ToList();

另一种选择是,如果您经常这样做,则可以将转换移动到扩展方法,这将允许您调用类似以下内容

var trees = _db.ItemCats.Select(Cat => Cat.ToTree()).ToList();