Casting short to boolean entity framework - c#

I am trying to convert a short value which represents a true or false in our system, -1(true), 0(false).
I was wondering if this kind of casting/conversion is possible inline where model property is being initialized.
public bool Foo {get;set;}
example:
return db.tblSomeTable
.Where( c => c.FooID == 1)
.Select( c => new SomeFooModel
{
FooID = id,
Foo = IsTrueOrFalse //value (-1, or 0)
}
I tried using a ternary operator but the syntax doesn't make sense:
IsFoo = if(IsTrueOrFalse == -1) ? true: false;, //syntax error it is obvious that ; is ending statement but the , there because there are more properties in this select.
The other way to do this might be to call a function that return true or false based on value passed in but I was wondering if this can be done with minimum lines of code.
Any suggestions?
Thanks

You can use a boolean expression
.Select(c => new SomeFooModel
{
Foo = (IsTrueOrFalse == -1)
}
or the conditional operator
.Select(c => new SomeFooModel
{
Foo = (IsTrueOrFalse == -1) ? true : false
}

The ternary statement is written like so:
IsFoo = (IsTrueOrFalse == -1) ? true : false
i.e. there is no need for the if and because there are other statements you also do not need the semi colon.
EDIT
As #juharr said in a comment if the value is anything other than -1, IsFoo will be set to false. So maybe you should do some extra checks. For example:
IsFoo = (IsTrueOrFalse == -1) ? true : (IsTrueOrFalse == 0) ? false : throw new ArgumentOutOfRangeException() //Or whatever
Although that will become unreadable fast.

Related

Use ?: Operand on entity framework

I want to use it in this way
Context.Moves.OfType<Cuotes>().Where(p =>
p.Final == true
&& dtFrom.DateTime != null ? p.DeliverDate >= dtFrom.DateTime : true
&& dtTo.DateTime != null ? p.DeliverDate <= dtToHasta.DateTime : true
&& !ckShowDelivered.Checked ? p.Delivered == false : true
&& !ckShowDelivered.Checked ? p.Canceled == false : true
);
Due I have muliple filters I tried to manipulate in this way, actually I have another checkbox to condition if old Cuotes versions are showed with Final == false statement, but this operand inside the Where clause seems to be not working.
It is a way to apply this operand or I must to hard code the if conditions for each combination of options posible?
You could just chain those in separate Where calls:
var result = Context.Moves.OfType<Cuotes>().Where(p => p.Final == true);
if (dtFrom.DateTime != null)
result = result.Where(p => p.DeliverDate >= dtFrom.DateTime);
if (dtTo.DateTime != null)
result = result.Where(p => p.DeliverDate <= dtToHasta.DateTime);
if (!ckShowDelivered.Checked)
result = result.Where(p => !p.Delivered);
if (!ckShowDelivered.Checked)
result = result.Where(p => !p.Canceled);
That way, you can use any kind of external conditions to affect your query without having to use those external conditions within the query itself.

Cannot implicitly convert type 'string' to 'bool' [If statement]

I have this validation in mvc
public static ValidationResult validaUsuariosNaLista(Reuniao item)
{
var requeridos = item.Requeridos.Select(x => x.Login).Any();
var informados = item.Informados.Select(y => y.Login).Any();
var opcionais = item.Opcionais.Select(z => z.Login ? z.Login : null).Any();
if (requeridos == informados || requeridos == opcionais || informados == opcionais)
return new ValidationResult(Resources.Validations.ValidaUsuarioMesmaLista);
return ValidationResult.Success;
}
I try make a different if in line
var opcionais = item.Opcionais.Select(z => z.Login ? z.Login : null).Any();
but show error
Error 3 Cannot implicitly convert type 'string' to 'bool'
z.Login is a string
validation is to make that the field has no value it receives null.
Without that it bursts the error that is null.
I want him to receive null without giving error for it.
It selects the z.login on the list if the same login is in the other lists he'm the error.
How can I do this "if" that way?
If z.Login is a string, then this expression is invalid:
z.Login ? z.Login : null
The first element in that expression needs to be a bool. What exactly are you trying to examine in that condition? Whether or not z.Login is null? If that's the case then you don't need a condition at all:
.Select(z => z.Login)
Since you'd just be replacing null with, well, null. Or if you want to interpret empty strings as null then you can use something like this:
.Select(z => string.IsNullOrEmpty(z.Login) ? nulll : z.Login)
Though it's not really clear what you're trying to accomplish with this line of code in the first place. .Any() is going to return a bool indicating whether or not any matching element exists in the collection at all. But since you're not using a predicate in .Any(), it's going to return true if there is any element in the collection at all. Which not only renders the .Select() pointless, but also doesn't tell you anything about that condition in the .Select().
Perhaps you are trying to find if there are any null values in the collection?:
item.Opcionais.Any(z => z.Login == null)
or any "null or empty" values?:
item.Opcionais.Any(z => string.IsNullOrEmpty(z.Login))
or the opposite, any non-empty values?:
item.Opcionais.Any(z => !string.IsNullOrEmpty(z.Login))
and so on...
z.Login is a string
validation is to make that the field has no value it receives null.
Do it like this:
Edit: Updated this section to also look for duplicates
public static ValidationResult validaUsuariosNaLista(Reuniao item)
{
var requeridos = item.Requeridos.Any(x => string.IsNullOrWhiteSpace(x.Login));
var informados = item.Informados.Any(x => string.IsNullOrWhiteSpace(x.Login));
var opcionais = item.Opcionais .Any(x => string.IsNullOrWhiteSpace(x.Login));
//does every item have a value?
if (requeridos || informados || opcionais)
return new ValidationResult(Resources.Validations.ValidaUsuarioMesmaLista);
//are all of the items unique?
if (item.Requeridos.Count() + item.Informados.Count() + item.Opcionais.Count() >
item.Requeridos.Concat(item.Informados).Concat(item.Opcionais).Distinct().Count)
{
//some items are duplicated
}
return ValidationResult.Success;
}
And, for fun, to avoid repeating code:
public static ValidationResult validaUsuariosNaLista(Reuniao item)
{
var HasEmptyValue = s => s.Any(x => string.IsNullOrWhiteSpace(x.Login));
//does every item have a value?
if (HasEmptyValue(item.Requeridos) || HasEmptyValue(item.Informados) || HasEmptyValue(item.Opcionais))
return new ValidationResult(Resources.Validations.ValidaUsuarioMesmaLista);
//are all of the items unique?
if (item.Requeridos.Count() + item.Informados.Count() + item.Opcionais.Count() >
item.Requeridos.Concat(item.Informados).Concat(item.Opcionais).Distinct().Count)
{
//some items are duplicated
}
return ValidationResult.Success;
}
Though I'm not 100% on how well type inference will work here... I'd have to see what the compiler makes of it, and I don't have your types to test with. But at worst, you'd just have to be explicit on the var declaration.
I think what you're trying to do is check if Login is null or empty. Assuming you want opcionais to be a boolean based on your .Any() statement:
var opcionais = item.Opcionais.Select(z => z.Login ? z.Login : null).Any();
should be
var opcionais = item.Opcionais.Any(z => !string.IsNullOrEmpty(z.Login));

EF The data types varchar and text are incompatible in the equal to operator

So I'm looking for a way in EntityFramework to do a string Comparison on TEXT Sql Field.
Every Solution I see to this problem tells them to Switch the Database Field from TEXT to nvarchar, which I cannot do.
This Code may seem intimidating but all of this works except for the line specified
var TitlesData = Mod.Titles.AsNoTracking().Where(t => !t.isTrackedMMS )
.Select(t => new
{
MK3ID = t.ID,
ExtTitleID = t.ExtTitleID,
CompletedSteps = new List<bool> {
true,
(t.TitleClasses.Any() || t.TitleToSearsTaxonomies.Any()),
(t.MediaDetailsStorages.Any(m => m.FK_StoreName == 2 || m.FK_StoreName == 3)),
(t.MediaDetails.FirstOrDefault().MasterDelivered.HasValue),
(t.MediaDetails.FirstOrDefault().MasterReceived.HasValue),
(t.MediaDetails.FirstOrDefault().Datecaptured.HasValue),
(t.MediaDetails.FirstOrDefault().DVDCreated.HasValue || !t.MediaDetails.FirstOrDefault().CreateDVD),
//This Line Throws an Error
(t.FullDescriptionHTML != ""),
}.Where(b => b).Count(),
SkipCollections = (t.ProductsToTitles.Any() || t.RoyaltyContract.ProductsToContracts.Any()),
SkipSegments = t.ByPassSegment.HasValue ? t.ByPassSegment.Value : false,
SkipEcom = t.Items.All(i => i.BlockFromSale.HasValue ? i.BlockFromSale.Value : false),
SentTrackingItems = t.SentTrackingEmails.Select(e => e.TrackingActionID).ToList()
}).ToList();
Does anybody know a way to do a string compare on The FullDescription html field
Thanks
It sounds like you dont have control of the database so how about comparing the length of the field to zero instead of an empty string
(len(t.FullDescriptionHTML) > 0
or doing a check for existence if comparing to null. Doing both might be a good idea?

Sequence contains no matching element Error using Boolean

bool Postkey =
statement
.ThreadPostlist
.First(x => x.ThreadKey == ThreadKey && x.ClassKey == classKey)
.PostKey;
This Ling query is giving me "Sequence contains no matching element" but I know I can use .FirstorDefault(). When I use .FirstorDefault() it will return me false, the default value for bool, when there are no matching records.
But I get a "Object not set to an instance of an object" error. I need to check the bool for null with .HasValue and .Value. I don't know how to do it.
Here is how you can use a nullable bool to solve this:
bool? postKey = null;
// This can be null
var post = statement.ThreadPostlist.FirstOrDefault(x=>x.ThreadKey == ThreadKey && x.ClassKey == classKey);
if (post != null) {
postKey = post.PostKey;
}
// Now that you have your nullable postKey, here is how to use it:
if (postKey.hasValue) {
// Here is the regular bool, not a nullable one
bool postKeyVal = postKey.Value;
}
You could do:-
bool? postkey = threadPostList
.Where(x=>x.ThreadKey == threadKey && x.ClassKey == classKey)
.Select(x => (bool?)x.PostKey)
.DefaultIfEmpty()
.First();
I think that better captures the intent of what you are trying to accomplish.
If you want to treat a null value as false (and don't want to use a nullable bool), you could just check if the resulting post is null before referencing the .PostKey property, like this:
var threadPost = statement.ThreadPostlist.FirstOrDefault(x =>
x.ThreadKey == ThreadKey && x.ClassKey == classKey);
bool PostKey = threadPost != null && threadPost.PostKey;
Or, a longer form would be:
bool PostKey;
if (threadPost != null)
{
PostKey = threadPost.PostKey;
{
else
{
PostKey = false;
}

Compare nullable types in Linq to Sql

I have a Category entity which has a Nullable ParentId field. When the method below is executing and the categoryId is null, the result seems null however there are categories which has null ParentId value.
What is the problem in here, what am I missing?
public IEnumerable<ICategory> GetSubCategories(long? categoryId)
{
var subCategories = this.Repository.Categories.Where(c => c.ParentId == categoryId)
.ToList().Cast<ICategory>();
return subCategories;
}
By the way, when I change the condition to (c.ParentId == null), result seems normal.
Other way:
Where object.Equals(c.ParentId, categoryId)
or
Where (categoryId == null ? c.ParentId == null : c.ParentId == categoryId)
The first thing to do is to put on logging, to see what TSQL was generated; for example:
ctx.Log = Console.Out;
LINQ-to-SQL seems to treat nulls a little inconsistently (depending on literal vs value):
using(var ctx = new DataClasses2DataContext())
{
ctx.Log = Console.Out;
int? mgr = (int?)null; // redundant int? for comparison...
// 23 rows:
var bosses1 = ctx.Employees.Where(x => x.ReportsTo == (int?)null).ToList();
// 0 rows:
var bosses2 = ctx.Employees.Where(x => x.ReportsTo == mgr).ToList();
}
So all I can suggest is use the top form with nulls!
i.e.
Expression<Func<Category,bool>> predicate;
if(categoryId == null) {
predicate = c=>c.ParentId == null;
} else {
predicate = c=>c.ParentId == categoryId;
}
var subCategories = this.Repository.Categories
.Where(predicate).ToList().Cast<ICategory>();
Update - I got it working "properly" using a custom Expression:
static void Main()
{
ShowEmps(29); // 4 rows
ShowEmps(null); // 23 rows
}
static void ShowEmps(int? manager)
{
using (var ctx = new DataClasses2DataContext())
{
ctx.Log = Console.Out;
var emps = ctx.Employees.Where(x => x.ReportsTo, manager).ToList();
Console.WriteLine(emps.Count);
}
}
static IQueryable<T> Where<T, TValue>(
this IQueryable<T> source,
Expression<Func<T, TValue?>> selector,
TValue? value) where TValue : struct
{
var param = Expression.Parameter(typeof (T), "x");
var member = Expression.Invoke(selector, param);
var body = Expression.Equal(
member, Expression.Constant(value, typeof (TValue?)));
var lambda = Expression.Lambda<Func<T,bool>>(body, param);
return source.Where(lambda);
}
My guess is that it's due to a rather common attribute of DBMS's - Just because two things are both null does not mean they are equal.
To elaborate a bit, try executing these two queries:
SELECT * FROM TABLE WHERE field = NULL
SELECT * FROM TABLE WHERE field IS NULL
The reason for the "IS NULL" construct is that in the DBMS world, NULL != NULL since the meaning of NULL is that the value is undefined. Since NULL means undefined, you can't say that two null values are equal, since by definition you don't know what they are.
When you explicitly check for "field == NULL", LINQ probably converts that to "field IS NULL". But when you use a variable, I'm guessing that LINQ doesn't automatically do that conversion.
Here's an MSDN forum post with more info about this issue.
Looks like a good "cheat" is to change your lambda to look like this:
c => c.ParentId.Equals(categoryId)
You need to use operator Equals:
var subCategories = this.Repository.Categories.Where(c => c.ParentId.Equals(categoryId))
.ToList().Cast<ICategory>();
Equals fot nullable types returns true if:
The HasValue property is false, and the other parameter is null. That is, two null values are equal by definition.
The HasValue property is true, and the value returned by the Value property is equal to the other parameter.
and returns false if:
The HasValue property for the current Nullable structure is true, and the other parameter is null.
The HasValue property for the current Nullable structure is false, and the other parameter is not null.
The HasValue property for the current Nullable structure is true, and the value returned by the Value property is not equal to the other parameter.
More info here Nullable<.T>.Equals Method
Or you can simply use this. It will also translate to a nicer sql query
Where((!categoryId.hasValue && !c.ParentId.HasValue) || c.ParentId == categoryId)
What about something simpler like this?
public IEnumerable<ICategory> GetSubCategories(long? categoryId)
{
var subCategories = this.Repository.Categories.Where(c => (!categoryId.HasValue && c.ParentId == null) || c.ParentId == categoryId)
.ToList().Cast<ICategory>();
return subCategories;
}
Linq to Entities supports Null Coelescing (??) so just convert the null on the fly to a default value.
Where(c => c.ParentId == categoryId ?? 0)

Categories

Resources