Returning some null values from a collection - c#

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;
});

Related

How can I remove all instances of a string within a string inside a list?

I have this code:
phraseSources.ToList().ForEach(i => i.JmdictMeaning ?? );
What I need to do, and I'm not it's possible using LINQ, is to remove all occurrences of a string looking like this:
[see=????????]
Note the ??? is meant to indicate there can be any amount of characters, except "]".
That appear inside of JmDictMeaning. Note there might be one or more of these but they will always start with "[see=" and end with "]"
In order to remove all [see=...] patterns you can try Regex.Replace:
using System.Text.RegularExpressions;
...
// Add ", RegexOptions.IgnoreCase" if required (if "See", "SEE" should be matched)
Regex regex = new Regex(#"\[see=[^\]]*\]");
// "abc[see=456]789" -> "abc789"
var result = regex.Replace(source, "");
In your case:
Regex regex = new Regex(#"\[see=[^\]]*\]");
var list = phraseSources.ToList();
list.ForEach(item => item.JmdictMeaning = regex.Replace(item.JmdictMeaning, ""));
Same idea if you want to filter out items with such strings:
var result = phraseSources
.Where(item => !regex.IsMatch(item.JmdictMeaning))
.ToList();
phraseSources.ToList().RemoveAll(i => i == "xyz");
Yours I imagine would probably look something like
phraseSources.ToList().RemoveAll(i => i.StartsWith("[see=") && i.EndsWith("]"));
Here's an example dotnetfiddle showing it in action
You can remove like this:
phraseSources.Select(ph => {ph.JmdictMeaning.Replace("[see=????????]", ""; return ph;})
.ToList();
Let me show an example:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
and query should look like this:
IList<Person> persons = new List<Person>()
{
new Person(){FirstName = "one1[see=????????]", LastName = "LastName1" },
new Person(){FirstName = "two1[see=????????]", LastName = "LastName1" },
new Person(){FirstName = "three1", LastName = "LastName1" },
new Person(){FirstName = "one[see=????????]", LastName = "LastName1" },
new Person(){FirstName = "two", LastName = "LastName1" },
};
persons = persons.Select(p => { p.FirstName = p.FirstName.Replace("[see=????????]", "");
return p; })
.ToList();

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
});

conditions in linq query

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.

Linq Lambda get two properties as string from aggretation

Inside a linq query to an anonymous select I want to concatenate strings from two properties.
For instance to find the full name of the oldest person in some grouping of persons.
var personsAndOldest = db.Persons.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson).Select(a => new
{
FirstName = a.FirstOrDefault().FirstName,
LastName = a.FirstOrDefault().LastName,
BirthDate = a.FirstOrDefault().BirthDate,
FullnameOfOldes = a.Aggregate((pers1, pers2) => pers1.BirthDate > pers2.BirthDate ? pers1 : pers2).FirstName + " " //How do I get LastName of the old one (without using the full aggregate again)
});
Do I have to write the full aggregation again to get the LastName after the firstname and whitespace?
You could use a lambda statement in the Select:
var personsAndOldest = db.Persons.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson).Select(a =>
{
var first = a.First();
var oldest = a.Aggregate((pers1, pers2) => pers1.BirthDate > pers2.BirthDate ? pers1 : pers2);
return new
{
FirstName = first.FirstName,
LastName = first.LastName,
BirthDate = first.BirthDate,
FullnameOfOldes = oldest.FirstName + " " + oldest.LastName)
};
});
You can do this as
var personsAndOldest = db.Persons
.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson)
.Select(g => new
{
a = g.First(),
o = g.Aggregate((pers1, pers2) =>
pers1.BirthDate > pers2.BirthDate ? pers1 : pers2)
})
.Select(pair => new
{
FirstName = pair.a.FirstName,
LastName = pair.a.LastName,
BirthDate = pair.a.BirthDate,
FullnameOfOldes = pair.o.FirstName + " " + pair.o.LastName
});
You can use let to introduce new range variables.
You don't need to specify property name for anonymous type if it equals name of assigned property
I think OrderBy will find oldest person (but you can use aggregate and compare performance)
I believe that oldest person is one with minimal birth date, so you need to change aggregation to pers1.BirthDate < pers2.BirthDate ? pers1 : pers2
So
var personsAndOldest = from p in db.Persons
group p by p.SomeThingThatCanBeGroupedForPerson into g
let first = g.FirtOrDefault()
let oldest = g.OrderBy(x => x.BirthDate).FirstOrefault()
select
{
first.FirstName,
first.LastName,
first.BirthDate,
FullnameOfOldes = oldest.FirstName + " " + oldest.LastName
};

Getting value from VAR

For the following code
var validate = from P in this.DataContext.Persons
where P.UserName.Equals(login) && P.Password.Equals(password)
select new
{
P.FirstName,
P.LastName,
P.EmailAddress
};
If record exists i want to get the first name and return it. How can i get the firstName from var validate?
validate here is going to be a set (IQueryable<T>) of data. You may need to use FirstOrDefault(), for example:
var record = validate.FirstOrDefault();
if(record != null) {
string firstName = record.FirstName;
}
Console.WriteLine(validate.FirstOrDefault().FirstName);
Otherwise you'll have to loop through the set since that what your query is returning Likely a set of one but it's still a set.
Try the following:
var validate = (from P in this.DataContext.Persons
where P.UserName.Equals(login) && P.Password.Equals(password)
select new
{
P.FirstName,
P.LastName,
P.EmailAddress
}).FirstOrDefault();
if (validate != null)
{
var firstName = validate.FirstName;
...
}

Categories

Resources