conditions in linq query - c#

I have a linq query that gets all data from customers and customer contacts.
But sometimes i don't want all contacts so i would like to specify a condition that if this value equals get contacts then run the query. Similar too..
switch (options)
{
case CustomerOptions.DefaultContacts:
break;
}
I currently have this linq query
var customersToReturn = new ContentList<CustomerServiceModel>()
{
Total = customers.Total,
List = customers.List.Select(c => new CustomerServiceModel
{
Id = c.Id,
ContractorId = c.ContractorId,
CompanyName = c.CompanyName,
Active = c.Active,
Address = new Address
{
Address1 = c.Address1,
Address2 = c.Address2,
Address3 = c.Address3,
Address4 = c.Address4,
},
CustomerContacts = c.CustomersContacts.Select(a => new ContactServiceModel
{
Name = a.Name,
Telephone = a.Telephone
}).Where(e => e.IsDefault)
}).ToList()
};
Is there a way I can set a condition or do I need to repeat the process twice one just for customers and one for customers and customer contacts?

If I understand it right, you want some of CustomServiceModel objects to have CustomerContacts, while others to have not? Then I'd do it like that
List = customers.List.Select(c => new CustomerServiceModel
{
Id = c.Id,
ContractorId = c.ContractorId,
CompanyName = c.CompanyName,
Active = c.Active,
Address = new Address
{
Address1 = c.Address1,
Address2 = c.Address2,
Address3 = c.Address3,
Address4 = c.Address4,
},
CustomerContacts = condition ?
c.CustomersContacts.Select(a => new ContactServiceModel
{
Name = a.Name,
Telephone = a.Telephone
}).Where(e => e.IsDefault)
:null
}).ToList()
If you need to use switch, create yourself a method that returns bool and put it instead of condition phrase in above example.

Related

Filter Criteria Search using LINQ

I am 'newer' to LINQ queries have another one of those questions where I have something going but not sure if this is the most effective way to go about it. In my project, I am working in a real DB, but for a sake of simplicity, here I will condense it down to a simple list of employees:
var employees = new List<Employee>
{
new Employee { Id = 0, firstName = "James", LastName = "Bond", Manager = "M", StartDate = DateTime.Now },
new Employee { Id = 1, firstName = "Eric", LastName = "Bond", Manager = "M", StartDate = DateTime.Now },
new Employee { Id = 2, firstName = "Sue", LastName = "Milton", Manager = "Q", StartDate = DateTime.Now },
new Employee { Id = 3, firstName = "Olivia", LastName = "Milton", Manager = "M", StartDate = DateTime.Now },
new Employee { Id = 4, firstName = "Alice", LastName = "Raymond", Manager = "M", StartDate = DateTime.Now },
new Employee { Id = 5, firstName = "James", LastName = "Skywalker", Manager = "M", StartDate = DateTime.Now },
new Employee { Id = 6, firstName = "Luke", LastName = "Skywalker", Manager = "M", StartDate = DateTime.Now },
};
I have to search in this list based on given criteria.. where criteria is combination of various fields with OR and AND operations with in the fields for example get me all employees where:
firstName = "James" OR "eric" AND manager = "Q"
lastname = "bond" OR "Martha"
firstName = "James" AND Lastname = "Bond"
and so on...
This is going to be a web API call and I have to do this in one method. The other challenge is that each search parameter is 'optional" i.e , they can pass me a list of firstnames and a manager name and ignore the last names parameters etc. So here is what I started coded:
public IList<Employee> GetFilteredEmployees(IList<String> firstnames = null,
IList<String> lastnames = null,
IList<String> managers = null)
{
if (firstnames != null && firstnames.Any())
{
foreach (var fn in firstnames)
{
employeeByFn = employees.Where(emp => emp.firstName == fn).ToList<Employee>();
}
}
if (lastnames != null && lastnames.Any())
{
foreach (var ln in lastnames)
{
employeeByLn = employees.Where(emp => emp.LastName == ln).ToList<Employee>();
}
}
..... // code ellided
}
As you can see, this is getting ugly even with a few search criteria parameters. In my real project, I have up to 16 of those. Also at the end of all these sub-queries, I have to merge my results into one employee list and return that keeping in mind that any of the sub-query result may be null.
I am sure this is not a unique problem and I see similar questions asked before but not exactly the same problem. What would be elegant way of doing this that is also easy to maintain .i.e if they decide to add more search criteria later (say by start Date), I want to be able to easily modify my method to handle that.
Thanks a bunch for looking.
You can keep on adding Where() conditions on the same result instead of creating many partial results.
public IList<Employee> GetFilteredEmployees(IList<String> firstnames = null,
IList<String> lastnames = null,
IList<String> managers = null)
{
IQueryable<Employee> result = employees;
if (firstnames != null)
result = result.Where(emp => firstnames.Contains(emp.firstName));
if (lastnames != null)
result = result.Where(emp => lastnames.Contains(emp.LastName));
if (managers != null)
result = result.Where(emp => managers.Contains(emp.Manager));
... // code ellided
return result.ToList();
}

Concatenate Int to String in LINQ Query

I have the following LINQ query.
var providers = from c in Repository.Query<Company>()
where !c.IsDeleted
select new { c.Description, Id = "C" + c.Id };
I'm trying to concatenate the ID to "C". So, for example, if c.Id is 35 then the result should be "C35".
This obviously doesn't work because you can't add an integer (c.Id) to a string. I could easily resolve this in C# using string.Format() or converting the type. But how can I do this in LINQ?
Try using SqlFunctions.StringConvert Method:
var xd = (from c in Repository.Query<Company>()
where !c.IsDeleted
select new { c.Description, Id = "C" + SqlFunctions.StringConvert((double)c.Id).Trim()});
When you need functionality of .NET only in preparing the result (as opposed to, say, filtering, which should be done on RDBMS side to avoid bringing too much data in memory) the common trick is to complete the conversion in memory using the AsEnumerable method:
var providers = Repository.Query<Company>()
.Where(c => !c.IsDeleted)
.Select(c => new { c.Description, c.Id }) // <<== Prepare raw data
.AsEnumerable() // <<== From this point it's LINQ to Object
.Select(c => new { c.Description, Id = "C"+c.Id }); // <<== Construct end result
The code that you have written will work fine. Here is a mock up of the same code and it outputs the Id's
class Company
{
public string Description { get; set; }
public int Id { get; set; }
public bool IsDeleted { get; set; }
}
static void Main()
{
//setup
var list = new List<Company>();
list.Add(new Company
{
Description = "Test",
Id = 35,
IsDeleted = false
});
list.Add(new Company
{
Description = "Test",
Id = 52,
IsDeleted = false
});
list.Add(new Company
{
Description = "Test",
Id = 75,
IsDeleted = true
});
/* code you are looking for */
var providers = from c in list
where !c.IsDeleted
select new { c.Description, Id = "C" + c.Id };
foreach (var provider in providers)
{
Console.WriteLine(provider.Id);
}
Console.ReadKey();
}
What about string format
var providers = from c in Repository.Query<Company>()
where !c.IsDeleted
select new { c.Description, Id = "C" + c.Id.ToString() };

Returning some null values from a collection

I have a LINQ query, I need to return all the customers in our database, however not all of them have a middle name. This is my query:
select new
{
firstName = a.firstname,
middleName = a.middlename,
lastName = a.lastname,
};
foreach(var c in queryAccount)
{
console.writeline(c.firstname);
console.writeline(c.middlename);
console.writeline(c.lastname);
}
What I am looking for is something similar to:
if (c.middlename != null)
{
console.writeline(c.middlename);
}
Does anyone know how I could get this to work?
You can simply use Null Colaescing operator:-
select new {
firstName = a.firstname,
middleName = a.middlename ?? String.Empty,
lastName = a.lastname,
};
Rahul's answer is correct. Additionally in case you don't want to assign 'middleName' at all you can do:
Select(x =>
{
var obj = new TestData
{
Lastname = x.Lastname,
Firstname = x.Firstname
};
if (!string.IsNullOrEmpty(x.Middlename))
obj.Middlename = x.Middlename;
return obj;
});

replacement for roundtrip serialize-deserialize

I've a table with over 100 column (including blobs) and I want to make a copy of object only with a few filled columns.
right now I'm doing it by selecting needed columns and doing a round-trip serialize and deserialize with Json.NET which is not efficient. what's the best way to handle this scenario?
BL.Case mCase;
BL.Case temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}).FirstOrDefault(u => u.CaseID == CaseID);
mCase = Newtonsoft.Json.JsonConvert.DeserializeObject<BL.Case>(Newtonsoft.Json.JsonConvert.SerializeObject(temp));
Use AutoMapper.
Do something like this:
BL.Case mCase = null;
var temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}).FirstOrDefault(u => u.CaseID == CaseID);
if (temp != null)
{
mCase = Mapper.DynamicMap<BL.Case>(temp);
}
Another solution that requires a bit more code (but might perform better) is to do the following:
In case you need a single item:
BL.Case mCase = null;
var temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}).FirstOrDefault(u => u.CaseID == CaseID);
if (temp != null)
{
mCase = new Case()
{
CaseID = temp.CaseID,
FirstName = temp.FirstName,
LastName = temp.LastName,
};
}
If you need multiple items:
var temp = db.Cases.Select(
xx => new
{
CaseID = xx.CaseID,
FirstName = xx.FirstName,
LastName = xx.LastName
}); //Here you can filter your query if you want using Where
var result = temp
.ToList() //This will actually execute the query on the database
.Select(x => new Case() //Now you can do this since now we are working on in-memory data
{
CaseID = x.CaseID,
FirstName = x.FirstName,
LastName = x.LastName
});

Entity Framework: Query is slow

I am having some problems with Entity Framework.
I have simplified this to make it easier to explain.
These are my mssql tables
I use the following code to get all cities for each of the countries in my MSSQL database
var country = new Country()
{
Cities = obj.Counties.SelectMany(e => e.Cities).Select(city => new DCCity
{
Name = city.Name,
Population = city.Population
})
};
This is returned as json
There is a bit more then 40.000 records in the city table. To retrieve a list with all the countries and their respective cities it takes around 8 seconds. I am trying to reduce this. Anyone know some optimization tips to achieve this?
You need to query the Cities table first to get all data:
var cities = _context.Cities.Select(x => new {
ContryId = x.County.Country.CountryId,
ContryName = x.County.Country.Name,
CityId = x.Id,
CityName = x.Name
});
var countryLookup = new Dictionary<int, CountryDto>(approximatelyCountOfCountries);
foreach (var city in cities)
{
CountryDto country;
if (!countryLookup.TryGetValue(city.CountryId, out country))
{
country = new CountryDto {
Name = city.CountryName,
Id = city.CountryId
Cities = new List<CityDto>(approximatelyCountOfCities)
};
countryLookup.Add(country.Id, country);
}
country.Cities.Add(new CityDto { Name = city.Name, Id = city.Id });
}
In this way the result will be the:
countryLookup.Values
Try to do somthing like this:
var result = from c in countries
join conty in counties on c.id equals conty.CountryId
join city in cities on conty.id equals city.CountyId
group city by c.Name into g
select new
{
Name = g.Key,
Cities = g.Select(x =>
new
{
x.Name,
x.Population
})
};

Categories

Resources