调用LINQ到实体的自定义(格式化)方法



我正在使用EF 4.1,我试图枚举一个网格的公司列表。在当前项目中,我有两个选项:从DbContext (Entities)中选择所有公司,并将它们从非匿名类型(假设EmpresaGrid)中加载到对象中,或者选择所有公司到具有相同结构的匿名类型对象中,如Empresa(这是我正在选择的实体)。

第一个选项(为此创建一个模型类)将需要更多的工作,但最终可以更可读。不过,我还是不确定。第二个选项是我现在正在使用的。

所以,第一个问题:最好创建一个模型类只显示数据或使用匿名类型?直接选择是毫无疑问的:SELECT *太大了,可能会使一切都变得非常慢(我猜)。因此,选择另一种类型将创建一个仅包含所需字段的自定义查询。

使用第二个选项(匿名类型),我有这样的代码(简化版本):
public static IEnumerable<object> Grid()
{
    Entities db = new Entities();
    var empresas = db.Empresas
        .Select(e => new
        {
            Cgc = e.Cgc, // PK
            (...)
            Address = new
            {
                AddressLine = e.EnderecoSede.AddressLine,
                (...)
            }
        },
        Contato = e.Contato,
        (...)
    })
    .ToList();
    return empresas;
}
我创建的匿名类型大约有40行代码,所以它有点大,但它重新创建了Empresa类结构的一部分(因为网格正在等待Empresa对象)。不管怎样,我对数据格式有点问题。例如,我想使用自定义字符串格式来格式化Cgc属性。我有一个公共方法,FormataCgc。这个方法接收一个字符串,并使用一些内部条件格式化后返回。 所以,我的问题是如何做到这一点。例如,我试过这样:
var empresas = db.Empresas
    .Select(e => new
    {
        Cgc = FormataCgc(e.Cgc),
    }

但这不起作用,因为FormataCgc不能转换为SQL(我不想转换它)。我还试了这个:

var empresas = db.Empresas
    .Select(e => new
    {
        (...)
    }
    .ToList();
foreach (var e in empresas) {
    e.Cgc = FormataCgc(e.Cgc);
}

但是这是不可能的,因为匿名类型只有只读属性。

所以,我的第二个问题是:我到底该怎么做?我需要改变数据后选择它,但使用匿名类型?我做了一些研究,我发现最好的事情是:在LINQ查询中调用自定义方法。在该解决方案中,Ladislav建议从IEnumerable中进行第二次选择,但由于网格除了Empresa,我不能这样做(我需要更改或添加属性,而不是封装它们)。

我不确定我是否讲得足够清楚,但请随时提问。此外,我目前使用的网格是Telerik ASP。. NET MVC网格,它接收一个IEnumerable(其中T是一个类)作为模型数据,然后迭代每个对象,发挥其魔力。

由于您已经将其转换为IEnumerable<T>,因此您可以在客户端流式传输结果时进行自定义格式化。做你的db。选择,然后转换为适当的格式,例如:

var empresas = db.Empresas
    .Select(e => new
    {
        (...)
    })
    .ToList();
foreach (var e in empresas) {
    yield return new {
       Cgc = FormataCgc(e.Cgc),
       // Copy other properties here, as needed...
    };
}

也就是说,我个人建议创建一个自定义类,而不是返回匿名类型。你的转换将是:

foreach (var e in empresas) {
    yield return new YourClass(FormataCgc(e.Cgc), ...); // Construct as needed
}

这将极大地提高该方法的可用性,因为您将从方法的调用者对属性有适当的命名访问。

我认为您的两个问题的解决方案是创建一个模型类。当然,在开始阶段会多做一些工作,但从长远来看,它会给你更大的灵活性。然后,您的自定义模型类可以为您处理格式。

public class EmpresaGridModel
{
    public string Cgc { get; set; }
    public string CgcFormatted 
    {
        return FormataCgc(this.Cgc);
    }
    //properties for the other fields will have to be created as well obviously
}

你的teleerik grid可以直接绑定到cgc格式化属性

最新更新