SQL转换为Linq到实体

时间:2015-09-30 19:22:28

标签: sql linq-to-entities

SQL请求:

DECLARE @search varchar(20)
set @search = '%a%'

Select distinct top (500) 
    Customer.Number,Contact.name, Address.StreetAddress, Phone.Number, 
    Customer.Type               
from 
    Customer
left join 
    dbo.Address on dbo.Customer.ContactId  = dbo.Address.ContactId
left join 
    dbo.Contact on dbo.Customer.ContactId  = dbo.Contact.Id
left join 
    dbo.Phone on dbo.Customer.ContactId  = dbo.Phone.ContactId 
              and Phone.Sequence = 1
where 
    Customer.IsActive = 1 
    and Customer.ContactId 
        in (--Primary Contact
            SELECT  Customer.ContactId
            FROM dbo.Customer
            INNER JOIN dbo.Contact ON dbo.Contact.id = dbo.Customer.ContactId
            LEFT JOIN dbo.Email ON dbo.Customer.ContactId  = dbo.Email.ContactId
            LEFT JOIN dbo.Phone ON dbo.Customer.ContactId  = dbo.Phone.ContactId
            LEFT JOIN dbo.Address ON dbo.Customer.ContactId  = dbo.Address.ContactId
            WHERE 
                Contact.FirstNameCareOf LIKE @search
                OR Contact.Name LIKE @search
                OR Email.Address LIKE @search
                OR Phone.Number LIKE @search
                OR Address.StreetAddress LIKE @search
                OR Address.City LIKE @search
                OR Address.ZipCode LIKE @search

          union

          --Secondary Contacts
          SELECT Customer.ContactId
          FROM dbo.Customer
          INNER JOIN dbo.Relationship ON dbo.Contact.Id = dbo.Relationship.TargetContactId
          INNER JOIN dbo.Contact on dbo.Contact.id = dbo.Relationship.SourceContactId
          LEFT JOIN dbo.Email ON dbo.Contact.Id = dbo.Email.ContactId
          LEFT JOIN dbo.Phone ON dbo.Contact.Id = dbo.Phone.ContactId
          WHERE 
            Contact.FirstNameCareOf LIKE @search
            OR Contact.Name LIKE @search
            OR Email.Address LIKE @search
            OR Phone.Number LIKE @search)
order by
    Customer.Number

这是我到目前为止所得到的:

from customerTable in Customers

    join contactTable in Contacts
        on customerTable.ContactId equals contactTable.Id

    join addressTable in Addresses
        on customerTable.ContactId equals addressTable.ContactId

    // the following may no exists for the customer so we dont want to join them since the customer will not be in the request results because of this  
    //  join phoneTable in Phones
    //      on customerTable.ContactId equals phoneTable.ContactId 
    //      
    //  join emailTable in Emails
    //      on customerTable.ContactId equals emailTable.ContactId

    // alternate method to query email and phone table without effecting the results    
    let emailMatch = Emails.Where (p => p.ContactId == customerTable.ContactId && p.Address.Contains("a"))
    let phoneMatch = Phones.Where (p => p.ContactId == customerTable.ContactId && p.Number.Contains("a"))

    where customerTable.IsActive && ( contactTable.Name.Contains("a") || contactTable.FirstNameCareOf.Contains("a") ||addressTable.StreetAddress.Contains("a") || addressTable.City.Contains("a") ||    
                                          addressTable.ZipCode.Contains("a") || emailMatch.Any()|| phoneMatch.Any() )
 orderby customerTable.Number 
            select new {CustomerNumber = customerTable.Number, contactTable.Name, addressTable.StreetAddress, customerTable.Type.EnumId}

问题

  1. 有没有一种简单的方法可以将我的SQL请求转换为linq到实体?过了一天,我还在玩上面的linq请求

  2. 在我的SQL请求中执行内连接和左连接的真实且最高效的方法是什么?

  3. 尝试转换EXACT SQL请求"语句"是否有意义到linq?或者在linq中使用完全不同的方法更好吗?我的意思是在SQL中执行此操作的最高效方法在linq中根本不一定是相同的方法吗?

  4. 当取消注释连接到手机....它不会返回没有手机的任何客户...是否可以返回结果,即使手机桌上没有任何东西可以加入客户?

  5. 感谢您提供任何帮助或任何事情。

2 个答案:

答案 0 :(得分:1)

您的前三个问题的回答是:使用导航属性。出于某种原因,来自SQL背景的人几乎总是开始用join语句编写LINQ。这至少有三个主要缺点:join语句 -

  • 是详细的
  • 没有揭示关联的多样性。声明

    from customerTable in Customers
    join contactTable in Contacts ...
    

    未告诉我,客户联系人是1-nn-1还是1-1

  • 容易出错:你必须输入连接列,你可以选错了(我已经看过它了。)

如果您使用正确命名的导航属性,例如

,这一切都会发生变化
from cust in Customers
from cont in cust.Contacts ...

它很短,它表明关联是1-n,您只需配置一次关联,而不再关心连接列。

因此,如果您这样做,您的查询将形如

from cust in Customers
where cust.Contacts
          .Any(cont => cont.Name.Contains("a")
                    || cont.FirstNameCareOf.Contains("a")
                    || cont.Address.StreetAddress.Contains("a")
                    || cont.Address.City.Contains("a")
                    || ...  )
   || cust.Relationships
          .Any(rel => rel.TargetContact.Name.Contains("a")
                   || rel.TargetContact.FirstNameCareOf.Contains("a")
                   || rel.TargetContact.Address.StreetAddress.Contains("a")
                   || rel.TargetContact.Address.City.Contains("a")
                   || ...  )
select cust

(如你所见,我必须猜测客户关系的多样性)

这将生成一个SQL查询,其中主谓词由EXIST语句组成。我认为这比INDISTINCT的组合更好,因为EXIST是一种有效的搜索策略。

关于您的第四个问题:您还可以在查询中包含电话中的匹配项以及|| cont.Phone == null

答案 1 :(得分:0)

好像你可以使用你正在搜索的4个实体并结合结果..

这是一个非常大的查询,但作为起点,你可以使用。

var contacts = from c in Contacts
               where c.FirstNameCareOf.Contains("c") ||
                     c.Name.Contains("c")
               select c.Customer;

var emails =   from e in Emails
               where e.Address.Contains("c")
               select e.Contact.Customer;

然后当您拥有所有客户时,只需将它们添加到列表中即可。

var customers = new List<Customer>();
customers.AddRange(contacts);
customers.AddRange(emails);
etc..