how to Merge results of two different entities in C#? - c#

IQueryable<v_Search> query = from pd in context.v_Search select pd;
IQueryable<t_HistoricAccountImport> xschistory = from pd in context.t_HistoricAccountImport select pd;
query = query.Where(x => names.Any(y => x.insured_name.Contains(y)));
xschistory = xschistory.Where(xsc => names.Any(y => xsc.insured_name.Contains(y)));
Both entities are present in same context
Now when i try below code to combine two results ,using union or concat ,which doesnt happen.
Try 1)
var results = query.concat(xschistory); //Caused error
var result1 = query.union(xschistory); //this also throws error
I also tried to select columns from the entity with similar datatype and values and tried to merge,
Try 2)
var res1 = query.ToList().Select
(x => new
{ x.insured_name ,
x.ReferenceNum
});
var res2 = xschistory.ToList().Select
(y=> new
{
y.insured_name,
y.program_id
});
var finalResults = res1.Union(res2); //Still got Error
is there anyway to accomplish this ?

One of the things you can do is bind them to
List<v_search> a; List<t_HistoricAccountImport> b;
and then
var together = a.Cast<object>().Concat(b.Cast<object>()).ToList();//cast preferably to something they both inherit from, and is not 'object'.
You cannot a.concat(b) now because the objects are not of the same type.

Related

How to check productid from two different database (compare two lists and return not matching items to add)

I have two databases, one is main and another is for add to cart.
I want to check add to cart prodid with main database prodid.
// here I get an error "data type issue" - that's why I convert to int
var db1prodid = Convert.ToInt32(db1.prod.Select(x => x.prodid).ToList());
var gg = Convert.ToInt32(db2.prod.Select(x => x.prodid).ToList().ToString());
var checkprodid = db2.prod.Where(x => gg == db1prodid ).ToList();
if you want to convert,
change your code as shown below:
var db1prodid = db1.prod.Select(x =>(int)x.prodid).ToList();
//or
var db1prodid = db1.prod.Select(x =>Convert.ToInt32(x.prodid)).ToList();
anyway, to compare two lists and return not matching items, you can do as below
var db1prodid = db1.prod.Select(x => Convert.ToInt32(x.prodid)).ToList();
var checkprodid = db2.prod.Where(x => !db1prodid.Contains(x.prodid)).ToList();
it'll return all rows in db2.prod that does not exist in db1.prod
At the same way,
var db2prodid = db2.prod.Select(x => Convert.ToInt32(x.prodid)).ToList();
var checkprodid = db1.prod.Where(x => !db1prodid.Contains(x.prodid)).ToList();
it'll return all rows in db1.prod that does not exist in db2.prod

Linq except two IEnumerable queries

I have a two linq query that returns type of IEnumerable. First query returns filtered values and second query return all values I want to except from second query to first query like minus operator in SQL and bind to my listboxs.
my code sample =>
using (ISession session = SessionManager.CurrentSession)
{
IEnumerable<RoleDefinition> roleAssigned = from groupRole in session.Query<GroupRole>()
join roleDef in session.Query<RoleDefinition>() on groupRole.RoleDefinitionId equals
roleDef.RoleDefinitionId
where groupRole.GroupId == SelectedGroupId
orderby roleDef.RoleName
select new RoleDefinition
{
RoleName = roleDef.RoleName
};
IEnumerable<RoleDefinition> roleUnassigned = from grole in session.Query<RoleDefinition>()
orderby grole.RoleName
select new RoleDefinition
{
RoleName = grole.RoleName
};
List<RoleDefinition> lRoleAss = roleAssigned.ToList();
List<RoleDefinition> lRoleUnAss = roleUnassigned.ToList();
lRoleUnAss = lRoleUnAss.Where(x => !lRoleAss.Contains(x)).ToList();
lsbAssigned.DataSource = lRoleAss;
lsbAssigned.TextField = "RoleName";
lsbAssigned.ValueField = "RoleName";
lsbAssigned.DataBind();
lsbUnAssigned.DataSource = lRoleUnAss;
lsbUnAssigned.TextField = "RoleName";
lsbUnAssigned.ValueField = "RoleName";
lsbUnAssigned.DataBind();
}
EDIT => I fixed my code as below and my function works successfully
List<RoleDefiniton> filteredUnassign = lRoleUnAss.Where(def => !lRoleAss.Select(x => x.RoleName).Contains(def.RoleName)).ToList();
Change the following line:
lRoleUnAss = lRoleUnAss.Where(x => !lRoleAss.Contains(x)).ToList();
To
var results = lRoleUnAss.Except(lRoleAss).ToList();
and use results to get the final list.
I declared a new variable because i do not know if you want to keep the initial list intact or not. If you do not mind changing it you may try:
lRoleUnAss = lRoleUnAss.Except(lRoleAss).ToList();

Performing a union in LINQ

I'm trying to get the union of these two queries but keep getting the following error:
'System.Linq.IQueryable<AnonymousType#1>' does not contain a definition for 'Union' and the best extension method overload 'System.Linq.ParallelEnumerable.Union<TSource>(System.Linq.ParallelQuery<TSource>, System.Collections.Generic.IEnumerable<TSource>)' has some invalid arguments
The linq queries look like this:
var g = from p in context.APP_PROD_COMP_tbl
where p.FAM_MFG == fam_mfg
group p by new
{
a_B_G = p.B_G,
a_MFG = p.MFG,
a_PRODUCT_FAM = p.PRODUCT_FAM,
};
var q = from p in context.APP_COMP_tbl
where p.FAM_MFG == fam_mfg
group p by new
{
a_B_G = p.a_B_G,
a_MFG = p.a_MFG,
a_PRODUCT_FAM = p.a_PRODUCT_FAM,
};
var data = q.Union(g);
I've tried using IEnumerable around the queries, but it still didn't work. Not really sure where I'm going wrong at this point, although admittedly LINQ isn't something I've had a ton of exposure to.
Update:
So I've gone in a slightly different direction from what I posted earlier. After doing more research, the group by statements were from old code and no longer needed for the intended purpose. I changed those to select new statements and had no further issue with the union.
I think that your problem here is type mismatch: g is of type IGrouping<AnonymousType#1, APP_PROD_COMP_tbl> and q is of type IGrouping<AnonymousType#1, APP_COMP_tbl>; this is why Union gives you the error.
I am not really sure what you are trying to Union (keys of the groups or groups of data themselves) but the solution would be:
If you want to union group keys, select the keys of your groups
var data = g.Select(x => x.Key).Union(q.Select(x => x.Key));
If you want to union the groups themselves then you need to project each element from both sequences into a common type, perform the grouping and then union the groups
var g = context.APP_PROD_COMP_tbl
.Where(p => p.FAM_MFG == fam_mfg)
.Select(ToCommonType)
.GroupBy(p => new
{
a_B_G = p.B_G,
a_MFG = p.MFG,
a_PRODUCT_FAM = p.PRODUCT_FAM,
});
var q = context.APP_COMP_tbl
.Where(p => p.FAM_MFG == fam_mfg)
.Select(ToCommonType)
.GroupBy(p => new
{
a_B_G = p.a_B_G,
a_MFG = p.a_MFG,
a_PRODUCT_FAM = p.a_PRODUCT_FAM,
});
var data = g.Union(q);
private CommonClass ToCommonType(APP_PROD_COMP_tbl item)
{
return new CommonClass
{
};
}
private CommonClass ToCommonType(APP_COMP_tbl item)
{
return new CommonClass
{
};
}
The problem is your Anonymouse types don't match:
var a = Enumerable.Range(1, 10).Select(x => new {a = x}).AsQueryable();
var b = Enumerable.Range(1, 10).Select(x => new {b = x}).AsQueryable();
var c = a.Union(b);
This won't work because typeof a is not same as typeof b
var a = Enumerable.Range(1, 10).Select(x => new {a = x}).AsQueryable();
var b = Enumerable.Range(1, 10).Select(x => new {a = x}).AsQueryable();
var c = a.Union(b);
But this will work, because Anonymouse types are the same.
You can try selecting same anonymouse types from your collection in q and g. Read more about Union for IQueryable
Union on IQueryAble<TSource>() accepts IQueryAble<TSource> as a parameter, so collection has to be the same type.

Can I combine two Linq calls when they use different syntax?

I have the following code. The function has a lot of Linq calls and I had help on putting this into place.
public IList<Content.Grid> Details(string pk)
{
IEnumerable<Content.Grid> details = null;
IList<Content.Grid> detailsList = null;
var data = _contentRepository.GetPk(pk);
var refType = this.GetRefType(pk);
var refStat = this.GetRefStat(pk);
var type = _referenceRepository.GetPk(refType);
var stat = _referenceRepository.GetPk(refStat);
details =
from d in data
join s in stat on d.Status equals s.RowKey into statuses
from s in statuses.DefaultIfEmpty()
join t in type on d.Type equals t.RowKey into types
from t in types.DefaultIfEmpty()
select new Content.Grid
{
PartitionKey = d.PartitionKey,
RowKey = d.RowKey,
Order = d.Order,
Title = d.Title,
Status = s == null ? null : s.Value,
StatusKey = d.Status,
Type = t == null ? null : t.Value,
TypeKey = d.Type,
Link = d.Link,
Notes = d.Notes,
TextLength = d.TextLength
};
detailsList = details
.OrderBy(item => item.Order)
.ThenBy(item => item.Title)
.Select((t, index) => new Content.Grid()
{
PartitionKey = t.PartitionKey,
RowKey = t.RowKey,
Row = index + 1,
Order = t.Order,
Title = t.Title,
Status = t.Status,
StatusKey = t.StatusKey,
Type = t.Type,
TypeKey = t.TypeKey,
Link = t.Link,
Notes = t.Notes,
TextLength = t.TextLength,
})
.ToList();
return detailsList;
}
The first uses one format for Linq and the second another. Is there some way that I could simplify and/or combine these? I would really like to make this code simpler but I am not sure how to do this. Any suggestions would be much appreciated.
Of course you can combine them. The Linq keywords such as from, where and select get translated into calls like the Extension methods that you call below, so effectively there's no difference.
If you really want to combine them, the quickest way is to put () around the first query, then append the method calls you use on details in the second query. Like this:
detailsList =
(from d in data // <-- The first query
// ...
select new Content.Grid
{
// ...
})
.OrderBy(item => item.Order) // <-- The calls from the second query
.ThenBy(item => item.Title)
.Select((t, index) => new Content.Grid()
{
//...
}).ToList();
But i think that would be ugly. Two queries are just fine IMO.

LINQ to SQL omit field from results while still including it in the where clause

Basically I'm trying to do this in LINQ to SQL;
SELECT DISTINCT a,b,c FROM table WHERE z=35
I have tried this, (c# code)
(from record in db.table
select new table {
a = record.a,
b = record.b,
c = record.c
}).Where(record => record.z.Equals(35)).Distinct();
But when I remove column z from the table object in that fashion I get the following exception;
Binding error: Member 'table.z' not found in projection.
I can't return field z because it will render my distinct useless. Any help is appreciated, thanks.
Edit:
This is a more comprehensive example that includes the use of PredicateBuilder,
var clause = PredicateBuilder.False<User>();
clause = clause.Or(user => user.z.Equals(35));
foreach (int i in IntegerList) {
int tmp = i;
clause = clause.Or(user => user.a.Equals(tmp));
}
var results = (from u in db.Users
select new User {
a = user.a,
b = user.b,
c = user.c
}).Where(clause).Distinct();
Edit2:
Many thanks to everyone for the comments and answers, this is the solution I ended up with,
var clause = PredicateBuilder.False<User>();
clause = clause.Or(user => user.z.Equals(35));
foreach (int i in IntegerList) {
int tmp = i;
clause = clause.Or(user => user.a.Equals(tmp));
}
var results = (from u in db.Users
select u)
.Where(clause)
.Select(u => new User {
a = user.a,
b = user.b,
c = user.c
}).Distinct();
The ordering of the Where followed by the Select is vital.
problem is there because you where clause is outside linq query and you are applying the where clause on the new anonymous datatype thats y it causing error
Suggest you to change you query like
(from record in db.table
where record.z == 35
select new table {
a = record.a,
b = record.b,
c = record.c
}).Distinct();
Can't you just put the WHERE clause in the LINQ?
(from record in db.table
where record.z == 35
select new table {
a = record.a,
b = record.b,
c = record.c
}).Distinct();
Alternatively, if you absolutely had to have it the way you wrote it, use .Select
.Select(r => new { a = r.a, b=r.b, c=r.c }).Distinct();
As shown here LINQ Select Distinct with Anonymous Types, this method will work since it compares all public properties of anonymous types.
Hopefully this helps, unfortunately I have not much experience with LINQ so my answer is limited in expertise.

Categories

Resources