【问题标题】:Calling custom (formatting) method on LINQ to Entities在 LINQ to Entities 上调用自定义(格式化)方法
【发布时间】:2011-08-29 20:04:14
【问题描述】:

我正在使用 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);
}

但由于匿名类型只有只读属性,所以不能这样做。

那么,我的第二个问题是:我究竟该怎么做?选择后需要更改数据,但使用匿名类型?我做了一些研究,发现最好的结果是:Calling a custom method in LINQ query。在该解决方案中,Ladislav 建议从 IEnumerable 中进行第二次选择,但由于网格不包含 Empresa,因此我无法这样做(我需要更改或添加属性,而不是封装它们)。

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

【问题讨论】:

    标签: c# entity-framework asp.net-mvc-3 linq-to-entities entity-framework-4.1


    【解决方案1】:

    由于您已经将其转换为 IEnumerable&lt;T&gt;,因此您可以在客户端中流式传输结果时进行自定义格式设置。做你的db.Select,然后转换成合适的格式,即:

    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
    }
    

    这将显着提高此方法的可用性,因为您可以从方法的调用者对您的属性进行适当的命名访问

    【讨论】:

      【解决方案2】:

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

      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
      }
      

      然后您的 Telerik 网格可以直接绑定到 CgcFormatted 属性

      【讨论】:

        猜你喜欢
        • 2015-06-06
        • 1970-01-01
        • 1970-01-01
        • 2012-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-02
        相关资源
        最近更新 更多