【问题标题】:Linq to entities - Formatting resultsLinq to entity - 格式化结果
【发布时间】:2015-10-01 17:55:58
【问题描述】:

我在格式化 linq 查询的结果时遇到问题

代码

var listOfCustomerSearchResult = (from customer in entities.Customers
        where customer.Number.StartsWith(customerNumber)
        select new CustomerSearchResult
        {
            AccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(0, customer.Number.IndexOf(".")) : customer.Number,
            SubAccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(customer.Number.IndexOf(".") + 1) : string.Empty,
            FirstAndLastName = (customer.Contact.IsIndividual) ? (customer.Contact.FirstNameCareOf + " " ?? string.Empty) + (customer.Contact.Name ?? string.Empty) : (customer.Contact.Name ?? string.Empty) + " " + (customer.Contact.FirstNameCareOf ?? string.Empty),
            StreetAddress = customer.Contact.Addresses.FirstOrDefault().StreetAddress ?? string.Empty,
            City = customer.Contact.Addresses.FirstOrDefault().City ?? string.Empty,
            ZipCode = customer.Contact.Addresses.FirstOrDefault().ZipCode ?? string.Empty,
            Region = customer.Contact.Addresses.FirstOrDefault().Region.Code ?? string.Empty,
            Delivery = string.Empty,
            IsActive = customer.IsActive,
            IsAdministrative = customer.IsAdministrative,
            SearchStep = 1,
            CustomerId = customer.Id,
            AccountType = customer.Type.EnumId,
            Phone = customer.Contact.Phones.FirstOrDefault().Number ?? string.Empty

        }).Take(500).ToList();

问题

1- 我需要格式化地址、电话等,但我不能直接在 Select new ... .) 不扫描所有结果并在执行查询后一一格式化每个结果?例如:像 MyQuery...blabla...Take(500).ToList().ImaginaryFormatProperties(x=> x.Phone = FormatPhone(x.Phone), x.Address = FormatAddress(x.Address) ...

2- 我需要多次调用这个查询,每次都有大量不同的 WHERE 子句。有没有办法做到这一点,而不必每次都创建 CustomerSearchResult 并分配这样的每个属性???我不想每次都重复这个设置部分,因为它没有改变

谢谢!

【问题讨论】:

  • 2:用谓词扩展 where 子句,这样您就可以在一个地方进行此查询

标签: c# linq linq-to-entities


【解决方案1】:

1.) 您可以向 CustomerSearchResult 模型类添加一个只读属性来为您进行格式化。

public class CustomerSearchResult
{
    //All of your current properties in this class  here


    //New readonly Property
    public string PhoneFormatedString
    {
        get
        {
            return //Do your formatting here using the Phone property, or pass it to a function
        }
    }
}

2.) 你想像这样创建一个 IQueryable 结果。

    public IQueryable<CustomerSearchResult> CustomerSearchBaseQuery()
    {
        IQueryable<CustomerSearchResult> listOfCustomerSearchResult = (from customer in entities.Customers
                                          select new CustomerSearchResult
                                          {
                                              AccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(0, customer.Number.IndexOf(".")) : customer.Number,
                                              SubAccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(customer.Number.IndexOf(".") + 1) : string.Empty,
                                              FirstAndLastName = (customer.Contact.IsIndividual) ? (customer.Contact.FirstNameCareOf + " " ?? string.Empty) + (customer.Contact.Name ?? string.Empty) : (customer.Contact.Name ?? string.Empty) + " " + (customer.Contact.FirstNameCareOf ?? string.Empty),
                                              StreetAddress = customer.Contact.Addresses.FirstOrDefault().StreetAddress ?? string.Empty,
                                              City = customer.Contact.Addresses.FirstOrDefault().City ?? string.Empty,
                                              ZipCode = customer.Contact.Addresses.FirstOrDefault().ZipCode ?? string.Empty,
                                              Region = customer.Contact.Addresses.FirstOrDefault().Region.Code ?? string.Empty,
                                              Delivery = string.Empty,
                                              IsActive = customer.IsActive,
                                              IsAdministrative = customer.IsAdministrative,
                                              SearchStep = 1,
                                              CustomerId = customer.Id,
                                              AccountType = customer.Type.EnumId,
                                              Phone = customer.Contact.Phones.FirstOrDefault().Number ?? string.Empty

                                          });

        return listOfCustomerSearchResult;
    }

然后你可以从你的 IQueryable 中查询。在调用 ToList() 之前不会执行 Sql

    public List<CustomerSearchResult> CustomerSearchByNumber(string customerNumber)
    {
        return CustomerSearchBaseQuery().Where(x => x.AccountNbr.StartsWith(customerNumber)).ToList();
    }

编辑 1:根据您的评论尝试使用 Func 需要做什么

//Customer here is the class from your entity model
    public static Expression<Func<Customer, CustomerSearchResult>> customerSelector = (customer) =>
    new CustomerSearchResult
    {
        AccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(0, customer.Number.IndexOf(".")) : customer.Number,
        SubAccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(customer.Number.IndexOf(".") + 1) : string.Empty,
        FirstAndLastName = (customer.Contact.IsIndividual) ? (customer.Contact.FirstNameCareOf + " " ?? string.Empty) + (customer.Contact.Name ?? string.Empty) : (customer.Contact.Name ?? string.Empty) + " " + (customer.Contact.FirstNameCareOf ?? string.Empty),
        StreetAddress = customer.Contact.Addresses.FirstOrDefault().StreetAddress ?? string.Empty,
        City = customer.Contact.Addresses.FirstOrDefault().City ?? string.Empty,
        ZipCode = customer.Contact.Addresses.FirstOrDefault().ZipCode ?? string.Empty,
        Region = customer.Contact.Addresses.FirstOrDefault().Region.Code ?? string.Empty,
        Delivery = string.Empty,
        IsActive = customer.IsActive,
        IsAdministrative = customer.IsAdministrative,
        SearchStep = 1,
        CustomerId = customer.Id,
        AccountType = customer.Type.EnumId,
        Phone = customer.Contact.Phones.FirstOrDefault().Number ?? string.Empty
    };

然后你的查询看起来像

var listOfCustomerSearchResult = entities.Customers.Where(x => x.Number.StartsWith(customerNumber)).Select(customerSelector).ToList();

【讨论】:

  • 谢谢似乎正是我所需要的......但是......该解决方案的问题是对象“客户”在 CustomerSearchByNumber 中不可用。例如:当尝试创建 CustomerSearchByContactName 时,我无法访问 customer.contact.name,因为客户在其他方法 (customerSearchBaseQuery) 中是否可以在 CustomerSearchBy.. () 方法中访问 c​​ustomer.contact?
  • 我编辑了我的回复。查看 EDIT 1 部分并尝试尝试一下。
  • 谢谢特拉维斯!我的问题已通过使用 func 方法仅在一个位置分配属性来解决。再次感谢!
【解决方案2】:

一种简单的方法是使用匿名类型收集这些额外信息。例如:

var listOfCustomerSearchResult = (from customer in entities.Customers
        where customer.Number.StartsWith(customerNumber)
        select new { CustomerSearchResult = new CustomerSearchResult
        {
            AccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(0, customer.Number.IndexOf(".")) : customer.Number,
            SubAccountNbr = (customer.Number.IndexOf(".") > 0) ? customer.Number.Substring(customer.Number.IndexOf(".") + 1) : string.Empty,
            FirstAndLastName = (customer.Contact.IsIndividual) ? (customer.Contact.FirstNameCareOf + " " ?? string.Empty) + (customer.Contact.Name ?? string.Empty) : (customer.Contact.Name ?? string.Empty) + " " + (customer.Contact.FirstNameCareOf ?? string.Empty),
            StreetAddress = customer.Contact.Addresses.FirstOrDefault().StreetAddress ?? string.Empty,
            City = customer.Contact.Addresses.FirstOrDefault().City ?? string.Empty,
            ZipCode = customer.Contact.Addresses.FirstOrDefault().ZipCode ?? string.Empty,
            Region = customer.Contact.Addresses.FirstOrDefault().Region.Code ?? string.Empty,
            Delivery = string.Empty,
            IsActive = customer.IsActive,
            IsAdministrative = customer.IsAdministrative,
            SearchStep = 1,
            CustomerId = customer.Id,
            AccountType = customer.Type.EnumId,
            Phone = customer.Contact.Phones.FirstOrDefault().Number ?? string.Empty

        }, FormatedPhone = FormatPhone(customer.Phone), ... ).Take(500).ToList();

这将使您无需通过查询执行搜索即可访问这些附加属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    相关资源
    最近更新 更多