C# Linq Union Returning Null - c#

I have a simple linq query that unionizes two tables that implement the same interface.
For this example, lets say IAnimal.
var q = (from d in db.Dogs
where d.AnimalID = PetID
select d.Name)
.Union
(from c in db.Cats
where c.AnimalID = PetID
select c.Name)
So if the dog portion has no members, q gets assigned {"", {whatever is in cat}}. Is there a way to remove that empty record without doing .Where(x=>x!="" | x!= String.Empty) after the query?
I know its not that big of a deal, but it seems like there should be a better way?

How is that not a good way? What is wrong with it?
Well.. there is one thing wrong with it. If should be:
.Where(x => !string.IsNullOrEmpty(x))
If you are using Entity Framework or some other LINQ provider which can't handle IsNullOrEMpty then the code should be:
.Where(x => x != null && x != "")
Your code using | instead of && and checks against the empty string twice but never null.

Related

How to use OR operator in Linq

I want to use OR function in my linq query.
Ex:
Sql:
select * from tblusers where userid=1 and status='a' or status='b';
Linq:
var result= _Repository.selectAll().where(x=>x.UserID==1 && x.status=="a" OR x.status=="B");
It's does work for linq query. so does anyone have any idea?
So you are aware about the && operator for comparison, then why not make a try with || operator? Anyway here is the solution for your problem, Following code will get you the result with UserID is 1 and status is either a or B.
_Repository.selectAll().where(x=>x.UserID==1 && (x.status=="a" || x.status=="B"));
Create an array of status you want to check and then use contains. something like this.
var statusList = new[] {"a", "b"};
.Where(x=> x.UserID == 1 && statusList.Contains(x.status));
Adding my 2 cents in here, there is another way you can write your sql query in C# which more or less resembles the sql syntax.
var result = from x in _Repository.SelectAll() where x.UserID == 1 && (x.Status == "a" || x.Status == "B") select x;
This syntax is Query Syntax/Expression where as your snippet is Method Syntax/Expression. Both will achieve same results. Also behind the scene, query syntax is compiled to Method syntax.
At compile time, query expressions are converted to Standard Query Operator method calls according to the rules set forth in the C# specification. Any query that can be expressed by using query syntax can also be expressed by using method syntax. However, in most cases query syntax is more readable and concise.
Or other approach with List.Contains, which generates sql query like
SELECT * FROM tblusers WHERE userid=1 AND status IN ('a','b');
var acceptedStatus = new List<string> { 'a', 'b' };
var result= _Repository.selectAll()
.Where(x => x.UserID == 1)
.Where(x => acceptedStatus.Contains(x.Status));
Notice that instead of && operator you can use another Where function and chain them. Can be more readable then fit all conditions in one line.
Try code:
var result =( from x in _Repository.selectAll()
where x.UserID==1 && (x.status=="a" || x.status=="B") select x);
another Solution
var result =( from x in _Repository.selectAll().where(c=>c.status=="a" || x.status=="B")
where x.UserID==1 select x);

Force the same behaviour using Linq to nHibernate with Oracle as Linq to collections when comparing columns containing null

Suppose I have a Man class defined in nHibernate
public class Man
{
public string Name {get;set;}
public string WifeName{get;set;}
public string OldestChildName {get;set;}
}
with some instances:
Name |WifeName |OldestChildeName
-------+-----------+-----------------
Mike |Penny |Jenny
Bill | |Julia
Tom |Patricia |Patricia
Peter | |
Bart |Mellany |
To select all persons where the oldest child name is the same as their wifes name
var names =
from m in men
where m.WifeName == m.OldestChildName
select m.Name
For Linq to collections this returns Tom and Peter.
But Linq to nHibernate to Oracle translates this to:
SELECT
m.name
FROM
men m
WHERE
m.WifeName = m.OldestChildName;
which returns just Tom: in SQL comparisons to null evaluate to null, and null evaluates to false.
What I'd like to see generated is:
SELECT
m.name
FROM
men m
WHERE
m.WifeName = m.OldestChildName
OR (
m.WifeName IS NULL
AND m.OldestChildName IS NULL
);
so in linq I need to type:
var names =
from m in men
where m.WifeName == m.OldestChildName
|| (m.WifeName == null && m.OldestChildName == null)
select m.Name
Is there a simple way to tell nHibernate to translate an equality comparison between two nullable colums, to a sql comparison and a null check?
In other words, is there a way to use the same linq query and get the same results regardless of if it's used for collections or databases?
All I could think of was building a pre-processor that parses the expression tree and modifies it to also emit the null checks. Has anybody already done this?
The sql query you need.
select * from Stack
where COALESCE (wifeName,'')=COALESCE (OldestChildeName,'')
Output.
You need to use Nhibernate queryover for it.
var left = Projections.SqlFunction("COALESCE",
NHibernateUtil.String,
Projections.Property<Stack>(pc => pc.OldestChildeName),
Projections.Constant(""));
var right = Projections.SqlFunction("COALESCE",
NHibernateUtil.String,
Projections.Property<Stack>(pc => pc.WifeName),
Projections.Constant("") );
var restriction = Restrictions.EqProperty(left, right);
var dd = contex.Session<Stack>().QueryOver<Stack>().Where(restriction).List();
Output.
ı suggest you lock

Entity Framework (using In and Select Distinct)

I am relatively new to Entity Framework 6.0 and I have come across a situation where I want to execute a query in my C# app that would be similar to this SQL Query:
select * from periods where id in (select distinct periodid from ratedetails where rateid = 3)
Is it actually possible to execute a query like this in EF or would I need to break it into smaller steps?
Assuming that you have in your Context class:
DbSet<Period> Periods...
DbSet<RateDetail> RateDetails...
You could use some Linq like this:
var distincts = dbContext.RateDetails
.Where(i => i.rateId == 3)
.Select(i => i.PeriodId)
.Distinct();
var result = dbContext.Periods
.Where(i => i.Id)
.Any(j => distincts.Contains(j.Id));
Edit: Depending on your entities, you will probably need a custom Comparer for Distinct(). You can find a tutorial here, and also here
or use some more Linq magic to split the results.
Yes, this can be done but you should really provide a better example for your query. You are already providing a bad starting point there. Lets use this one:
SELECT value1, value2, commonValue
FROM table1
WHERE EXISTS (
SELECT 1
FROM table2
WHERE table1.commonValue = table2.commonValue
// include some more filters here on table2
)
First, its almost always better to use EXISTS instead of IN.
Now to turn this into a Lambda would be something like this, again you provided no objects or object graph so I will just make something up.
DbContext myContext = this.getContext();
var myResults = myContext.DbSet<Type1>().Where(x => myContext.DbSet<Type2>().Any(y => y.commonValue == x.commonValue)).Select(x => x);
EDIT - updated after you provided the new sql statement
Using your example objects this would produce the best result. Again, this is more efficient than a Contains which translates to an IN clause.
Sql you really want:
SELECT *
FROM periods
WHERE EXISTS (SELECT 1 FROM ratedetails WHERE rateid = 3 AND periods.id = ratedetails.periodid)
The Lamda statement you are after
DbContext myContext = this.getContext();
var myResults = myContext.DbSet<Periods>()
.Where(x => myContext.DbSet<RateDetails>().Any(y => y.periodid == x.id && y.rateid == 3))
.Select(x => x);
Here is a good starting point for learning about lamda's and how to use them.
Lambda Expressions (C# Programming Guide).
this is your second where clause in your query
var priodidList=ratedetails.where(x=>x.rateid ==3).DistinctBy(x=>x.rateid);
now for first part of query
var selected = periods.Where(p => p.id
.Any(a => priodidList.Contains(a.periodid ))
.ToList();

C# SQL To Linq - Where Clause with multiple variables Comparison (var1+var2) !=(var1+var2)

I have these working in sql for large data set working great. However I'm having hard time converting to linq-I'm new to linq
Select * from table1 t1, table2 t2 where (t1.RoleId+t1.UserId)!=(t2.RoleId+t2.UserId).
On a side note, when the two variables are separated, I get undesired results.
Meaning the following: where (t1.RoleId != t2.RoleId && t1.UserId != t2.UserId)
In c# I have two anonymous lists. The last linq statement works great till nulls come into the picture. Nothing returns. I even thought of using a left join with no success.
So how would you tackle the above query with anonymous type lists?
Linq statments I have so far
var roleUserList =
(
from rls in roleResouceList
join user in userResourceList
on rls.FullResource.ToUpper() equals user.FullResource.ToUpper()
orderby rls.RoleID, user.UserID, rls.Res1, rls.Res2, rls.Res3
select new
{
RoleID = rls.RoleID,
UserID = user.UserID,
ServerId = rls.ServerID,
FullResource = rls.FullResource,
RlsRes1 = rls.Res1,
RlsRes2 = rls.Res2,
RlsRes3 = rls.Res3
}).Distinct().ToList();
var missingRoleUserList =
(
from rls in rlsCount
join usr in usrCount
on rls.Res1 equals usr.Res1
where rls.Total > usr.Total
select new
{
UserID = usr.UsrID,
RoleID = rls.RoleID
}).Distinct().ToList();
List<string> outputRoleUserList =
(
from rls in roleUserList
from mis in missingRoleUserList
where (rls.RoleID + rls.UserID) != (mis.RoleID +mis.UserID)
select rls.UserID + ",\"" + rls.RoleID
).DefaultIfEmpty().Distinct().ToList();
I'm not entirely certain that this is what you're looking for, but I'm going to give it a shot:
Try chaining your where clauses in Linq to SQL, and you may get a better result:
List<string> outputRoleUserList =
from rls in roleUserList
from mis in missingRoleUserList
where rls.RoleID != mis.RoleID
where rls.UserID != mis.UserID
select rls.UserID + ",\"" + rls.RoleID
This will actually generate SQL as follows:
rls.RoleId != mis.UserID AND rls.UserId != mis.UserID
However, you have already forced execution on roleUserList and missingRoleUserList, so what you're using in the third Linq statement is not really Linq to SQL but rather Linq to Objects, if I'm reading this correctly.
I'd be curious to see some additional information or clarification and then maybe I'll understand better what's going on!
EDIT: I realized another possibility, it's possible that the object.UserID or object.RoleID is throwing an internal NullPointerException and failing out because one of those values came back null. You could possibly solve this with the following:
List<string> outputRoleUserLIst2=roleUserList
.Where(x => x != null && x.UserID != null && x.RoleID != null && missingRoleUserList
.Where(y => y != null && y.UserID != null && y.RoleID != null && y.RoleID!=x.RoleID && y.UserID!=x.UserID)
.FirstOrDefault()!=null)
.Select(x => x.UserID + ",\"" + x.RoleID).Distinct().ToList();
This is not pretty, and this is the other Linq syntax (with which I am more comfortable) but hopefully you understand what I am going for here. I'd be curious to know what would happen if you dropped this into your program (If I've guessed all of your meanings correctly!). I'll look back in a bit to see if you have added any information!

Linq type checking 3 times - is there a better shape?

I have a Linq expression that operates on a list of objects for which one of said objects properties I need to type check before making use of it.
Example:
IEnumerable<Employee> activeAuditOwners = (
from objectStateEntry in objectStateEntries
where ( objectStateEntry.Entity is IAuditEntity ) == true
&& ( objectStateEntry.Entity as IAuditEntity ).Active == true
select ( objectStateEntry.Entity as IAuditEntity ).Owner
);
My concern is that I use type checking 3 times ( is, as, as ) which doesn't feel very DRY.
Is there a better shape for this query that avoids this (without creating a second query)?
UPDATE: Thanks for the great answers, I have tidied the example a bit for future readers.
What about OfType extension method:
var data = from a in auditObjectStateEntries.OfType<IAuditEntity>()
where a.Active
select a.Owner;
Edit:
I overlooked .Entity part so the correct query is:
var data = from e in auditObjectStateEntries.Select(a => a.Entity).OfType<IAuditEntity>()
where e.Active
select e.Owner;
There are some good solutions here, but I would use OfType like this:
IEnumerable<Employee> activeAuditOwners = objectStateEntries
.Select(s => s.Entity)
.OfType<IAuditEntry>()
,Where(e => e.Active)
.Select(e => e.Owner);
One way would be to use the let clause:
from auditObjectStateEntry in auditObjectStateEntries
let entity = auditObjectStateEntries.Entity as IAuditEntity
where entity != null
&& entity.Active
select entity.Owner
Yup, you can use the let expression:
from auditObjectStateEntry in auditObjectStateEntries
let auditEntity = auditObjectStateEntry.Entity as IAuditEntry
where auditEntity != null
&&
auditEntry.Active
select auditEntry
Update:
I forgot about OfType<T> as suggested by other answerer. Definitely a cleaner solution for this, so recommend using that approach instead.
First of all, you can forget the is, you don't need it. Per this documentation:
expression as type
is equivalent to:
expression is type ? (type)expression : (type)null
So you can simplify your code by using a single conversion attempt, perhaps something like this:
IEnumerable<Employee> activeAuditOwners = (
from auditObjectStateEntry in auditObjectStateEntries
let entity = auditObjectStateEntry.Entity as IAuditEntry
where entity != null && auditEntry.Active
select auditEntry.Owner
);

Categories