Bmize729
Bmize729

Reputation: 1136

Entity Framework select multiple columns and return the one that is not null

I am building a URL using variables from entities. I would like to select a user record based on ID and return either the mobile or landline, default mobile but if it is blank then landline. Below is my current code:

var phone = context.Addresses
                .Where(x => x.ClientID == clientID)
                .Select(x => x.Mobile)
                .FirstOrDefault();

            var webClient = new WebClient();
            var url = String.Format(Urls.CreateClientUrl,
                settings.EntityID,
                settings.ClinicID,
                UserID.Value,
                clientID,
                client.FirstName,
                client.LastName,
                email,
                phone);

Obviously this work for phone and returns the string mobile but if it is empty, I would like to return the string phone. Below is what I have tried:

                var phone = context.Addresses
                .Where(x => x.ClientID == clientID)
                .Select(x => new { x.Mobile, x.Phone })
                .FirstOrDefault();

            var webClient = new WebClient();
            var url = String.Format(Urls.CreateClientUrl,
                settings.EntityID,
                settings.ClinicID,
                UserID.Value,
                clientID,
                client.FirstName,
                client.LastName,
                email,
                phone);

This returns both strings. I would like to only get the string Phone in the event that mobile is empty.

I have followed a few other threads in SO but my limited knowledge is only returning broken code.

Upvotes: 0

Views: 579

Answers (2)

Harshad Raval
Harshad Raval

Reputation: 79

Try this:

var phone = context.Addresses.Where(x => x.ClientID == clientID).Select(x => x.Mobile ?? x.Phone).FirstOrDefault();

Or

var phone = context.Addresses.Where(x => x.ClientID == clientID).Select(x => x.Mobile).FirstOrDefault();
if (test == null || test == "")
{
    phone = context.Addresses.Where(x => x.ClientID == clientID).Select(x => x.Phone).FirstOrDefault();
}

Upvotes: 0

Caius Jard
Caius Jard

Reputation: 74595

If by "blank" and "empty" you mean null, you can use null propagation operator

string phone = "123";
string mobile = null;

string mobileThenPhone = mobile ?? phone; 

You can even use it multiple times

string mobileThenPhoneThenDefault = mobile ?? phone ?? "No contact info";

So in your case e.g

string.Format(..., mobile ?? phone ?? "Some default")

You can't always use it in a LINQ query that is being translated to SQL but it looks like that doesn't apply here because you've downloaded the data by the time you're formatting it. If you do hit a "cannot contain a null propagation" error in an EF query you can either look to swap it for a more typical something == null ? otherthing : something, or download both things from the db and evaluate it for null in c#


If by "blank" and "empty" you mean "" or "contains only whitespace" you can use

string.IsNullOrWhiteSpace(mobile) ? phone : mobile

It's not quite as compact as null propagation and you should avoid nesting it because, though possible, it gets unreadable pretty quickly:

string.IsNullOrWhiteSpace(mobile) ? )string.IsNullOrWhiteSpace(phone) ? "default" : phone) : mobile

To tidy that up you could define an extension method on string:

static string IfBlank(this string test, string alternative){
  return string.IsNullOrWhiteSpace(test)?alternative:test;
}

And then use it like:

mobile.IfBlank(phone).IfBlank("default");

But beware if mobile is null you'll have to kick things off like this to avoid a crash:

(mobile??"").IfBlank(phone).IfBlank("default");

Upvotes: 1

Related Questions