开发者

How to declare the result of query in LINQ to Entities

开发者 https://www.devze.com 2023-04-13 00:15 出处:网络
I just started using MS entity framework and have the following problem with LINQ. I will simplify my problem to make it clearer; let\'s say that I have three tables in SQL Server database:

I just started using MS entity framework and have the following problem with LINQ. I will simplify my problem to make it clearer; let's say that I have three tables in SQL Server database:

  • CustomerData (PK is CustomerId, the table also has some twenty columns to hold customer data).
  • CustomerData1 (holds some data for the customer in one to one relationship).
  • CustomerData2 (also holds some data for the customer in one to one relationship).

I know the data with one to one relationship should better be in the same table, but this is some corporate db and it is not possible to alter the original table (so all our data should be in the separate tables).

Now I want to display a list of customer with their data from CustomerData table and add some data columns from CustomerData1 via join. On the other hand, I want to display a list of customers and add some data from the other table CustomerData2 via join.

So the data is basically the same both times except that in the first case the result includes some columns from CustomerData1 and in the second case some data from CustomerData2 table.

So I created the class Customer with properties for all relevant columns in CustomerData table and added properties for columns that should be included from CustomerData1 and properties that should be included from CustomerData2. All columns should be included each time, except that when first call will be made the properties that map to CustomerData2 table will be empty and during the second call the properties that map to CustomerData1 table will be empty.

For this I wanted to create one function so I tried to create it like this: Input parameter in function is whether data from CustomerData1 or CustomerData2 is included.

if (firstList)
{
  var query1 = from obj in CustomerData
               join rel in CustomerData1
               on 开发者_如何转开发obj.CustomerId equals rel.CustomerId 
               select new { obj, rel };
}

if (secondList)
{
   var query2 = from obj in CustomerData
               join rel in CustomerData2
               on obj.CustomerId equals rel.CustomerId 
               select new { obj, rel };
}

So this code gives me the anonymous type based on the input parameter. Now I want to create Customer objects and order it (order is always the same, it does not depend on input parameter). So I want to create a list of ordered customers and include additional data based on the input parameter.

var query3 = <previous_query_variable>.Select(f => new Customer {
Id = f.obj.CustomerId,
Name = f.obj.CustomerName,
... other columns from Customer table (a lot of them)
//and then add some additional columns based on the input parameter
Data1 = f.rel.someDataFromCustomer1, //only when firstList == true, otherwise empty
Data2 = f.rel.someDataFromCustomer2  //only when secondList == true, otherwise empty
}).OrderBy(f => f.Name); //order by customer name

Of course this does not compile, since both vars are inside if statements. I know I could copy this last statement (var query3 = ...) inside both if statements and include only relevant assignments (Data1 or Data2), but I don't want to assign properties that map to CustomerData table twice (once in both if statements) nor I want to order twice.

How can I solve this problem? I am using .NET 4.


You cannot declare a variable for an anonymous type up-front, i.e. before your two if statements. (Something like var query = null is not supported.) You will have to create a helper type and project into it, like so:

public class ProjectedCustomerData
{
    public CustomerData CustomerData { get; set; }
    public CustomerData1 CustomerData1 { get; set; }
    public CustomerData2 CustomerData2 { get; set; }
}

And then the projection:

IQueryable<ProjectedCustomerData> resultQuery = null;
if (firstList)
{
    resultQuery = from obj in CustomerData
                  join rel in CustomerData1
                  on obj.CustomerId equals rel.CustomerId 
                  select new ProjectedCustomerData
                  {
                      CustomerData = obj,
                      CustomerData1 = rel
                  };
}
if (secondList)
{
    resultQuery = from obj in CustomerData
                  join rel in CustomerData2
                  on obj.CustomerId equals rel.CustomerId 
                  select new ProjectedCustomerData
                  {
                      CustomerData = obj,
                      CustomerData2 = rel
                  };
}

var query3 = resultQuery.Select(f => new Customer {
    Id = f.CustomerData.CustomerId,
    Name = f.CustomerData.CustomerName,
    // ...
    Data1 = f.CustomerData1.someDataFromCustomer1,
    Data2 = f.CustomerData2.someDataFromCustomer2
}).OrderBy(f => f.Name);

I am not sure if Customer is an entity in your model or only a class you are using for your projection. If it's an entity you have to change the last code because you cannot project into an entity (basically you would need another helper type for your projection).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号