Linq-To-Entities使用方法选择新对象

5

我想在我的应用程序中多次使用相同的选择查询语句。例如,我有以下选择语句:

 _db.tbl_itembundlecontents
                    .Select(z => new SingleItemDTO
                    {
                        amount = z.amount,
                        id = z.id,
                        position = z.position,
                        contentType = new BasicMaterialDTO
                        {
                            id = z.tbl_items.id,
                            img = z.tbl_items.tbl_material.img,
                            name = z.tbl_items.tbl_material.name,
                            namekey = z.tbl_items.tbl_material.namekey,
                            info = z.tbl_items.tbl_material.info,
                            weight = z.tbl_items.tbl_material.weight
                        }
                    });

但是我也有这个:
 _db.tbl_itembundle
                .Where(x => x.type == 2)
                .Select(y => new ItemBundleDTO
                {
                    name = y.name,
                    namekey = y.namekey.
                    contents = y.tbl_itembundlecontents
                    .Select(z => new SingleItemDTO
                    {
                        amount = z.amount,
                        id = z.id,
                        position = z.position,
                        contentType = new BasicMaterialDTO
                        {
                            id = z.tbl_items.id,
                            img = z.tbl_items.tbl_material.img,
                            name = z.tbl_items.tbl_material.name,
                            namekey = z.tbl_items.tbl_material.namekey,
                            info = z.tbl_items.tbl_material.info,
                            weight = z.tbl_items.tbl_material.weight
                        }
                    })
                });

您可以看到,我在两个linq选择语句中使用完全相同的代码(用于SingleItemDTO)。有没有一种方法可以将我的第一个选择语句的代码分开(而不会出现NotSupportedException),并再次重用它?我的第二个查询应该如下:

_db.tbl_itembundle
                .Where(x => x.type == 2)
                .Select(y => new ItemBundleDTO
                {
                    name = y.name,
                    namekey = y.namekey.
                    contents = y.tbl_itembundlecontents.ToDTO()
                });
3个回答

8

这是可能的,但需要以一种不太常见的方式进行。

创建一个助手方法,并将您第一个查询中的选择器部分移动到以下位置

static Expression<Func<[tbl_itembundlecontents entity type], SingleItemDTO>> ToSingleItemDTO()
{
    return z => new SingleItemDTO
    {
        amount = z.amount,
        id = z.id,
        position = z.position,
        contentType = new BasicMaterialDTO
        {
            id = z.tbl_items.id,
            img = z.tbl_items.tbl_material.img,
            name = z.tbl_items.tbl_material.name,
            namekey = z.tbl_items.tbl_material.namekey,
            info = z.tbl_items.tbl_material.info,
            weight = z.tbl_items.tbl_material.weight
        }
    };
}

现在,第一个查询可以是这样的:
_db.tbl_itembundlecontents.Select(ToSingleItemDTO());

第二段翻译内容如下

_db.tbl_itembundle
    .Where(x => x.type == 2)
    .Select(y => new ItemBundleDTO
    {
        name = y.name,
        namekey = y.namekey.
        contents = y.tbl_itembundlecontents.AsQueryable().Select(ToSingleItemDTO())
    });

请注意导航属性后面的AsQueryable(),这是使其正常工作的关键部分。

2

像这样的东西吗?

public static class HelperExtension
{
    public static IEnumerable<SingleItemDTO> ToDto(this IEnumerable<Tbl_itembundlecontents> items)
    {
        return items.Select(z => z.ToDto());
    }

    public static SingleItemDTO ToDto(this Tbl_itembundlecontents z)
    {
        return new SingleItemDTO
        {
            amount = z.amount,
            id = z.id,
            position = z.position,
            contentType = new BasicMaterialDTO
            {
                id = z.tbl_items.id,
                img = z.tbl_items.tbl_material.img,
                name = z.tbl_items.tbl_material.name,
                namekey = z.tbl_items.tbl_material.namekey,
                info = z.tbl_items.tbl_material.info,
                weight = z.tbl_items.tbl_material.weight
            }
        };
    }
}

这将抛出相同的异常。 - haim770
啊,抱歉,是Linq to SQL转换引发了异常,我知道这有点作弊,但你可以使用.Where(x => x.type == 2).ToList(),然后进行投影。 - Robbert Draaisma
是的,调用 ToList() 可能是最简单的方法。然而,这意味着生成的 SQL SELECT 语句可能包含不必要的字段,并且在映射期间进一步访问导航属性会调用额外的查询(使用延迟加载机制)。 - haim770
1
正如 @haim770 已经提到的,我不想选择不必要的字段。但是 LinqKit 可能就是我正在寻找的扩展。 - yDeveloper

0
或者类似这样的东西?
public object[] BicagiKullanabilenMakinalar { get; set; }

item.BicagiKullanabilenMakinalar = await (from bicak in _dbContext.BicakMakinas
                                      join islem in _dbContext.Islems on bicak.Islemkod equals islem.Islemkod into islemInto
                                      from islem in islemInto.DefaultIfEmpty()
                                      join makina in _dbContext.MakinaKarts on bicak.Makinakodu equals makina.Makinakodu into makinaInto
                                      from makina in makinaInto.DefaultIfEmpty()
                                      where islem.Islemtipkod == "002"
                                      && bicak.Bicakkodu == bicakKodu
                                      select new
                                      {
                                          MakinaKodu = bicak.Makinakodu,
                                          MakinaAdi = makina.Makinaadi,
                                          KodAciklama = islem.Kodaciklama
                                      })
                                      .Distinct()
                                      .OrderBy(e => e.MakinaAdi)
                                      .ToArrayAsync(cancellationToken);

回应;
   "bicagiKullanabilenMakinalar": [
        {
            "makinaKodu": "003",
            "makinaAdi": "GALLUS R200B",
            "kodAciklama": "BIÇAKLAMA (TAHTA DISLI)"
        },
        {
            "makinaKodu": "004",
            "makinaAdi": "ZONTEN",
            "kodAciklama": "BIÇAKLAMA (TAHTA DISLI)"
        }
    ],

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接