Linq except two IEnumerable queries - c#

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

Related

C# Linq nested selects not returning everything

I'm trying to select information from multiple tables via Linq. The query works if I take out the last Api query from apis in Database.PluginApis where apis.PluginId == tenantPlugin.PluginId. If I put the query back in, it results in an error System.Collections.Generic.KeyNotFoundException: The given key 'Name' was not present in the dictionary. Anyone able to see what I am doing wrong?
var results = (from tenantPlugin in Database.TenantPlugins
where tenantPlugin.TenantId == tenantId
select new TenantPlugin
{
PluginId = tenantPlugin.PluginId,
IsEnabled = tenantPlugin.IsEnabled,
TenantId = tenantPlugin.TenantId,
TenantPluginId = tenantPlugin.TenantPluginId,
Plugin = (from plugin in Database.Plugins
where plugin.PluginId == tenantPlugin.PluginId
select new Plugin
{
PluginId = plugin.PluginId,
Name = plugin.Name,
Description = plugin.Description,
ImagePath = plugin.ImagePath,
IsActive = plugin.IsActive,
Apis = (from apis in Database.PluginApis
where apis.PluginId == tenantPlugin.PluginId
select new PluginApi
{
Name = apis.Name
}).ToList<PluginApi>()
}).FirstOrDefault<Plugin>()
});
return results.ToList();
It's seems you have a perfect case to use Include() method. Try:
var results = Database.TenantPlugins
.Include(t => t.Plugin.Select(p => p.Apis))
.Where(t => t.TenantId == tenantId);

Retrieving data from 2 different SQL table to datagridview using Linq to Sql

I have two tables in sql and i want to retrieve and fill a datagridview using 4 column from first table and 1 column from second table. My problem is, i am doing some ordering for the data from first table and i couldn't figure out how to join second table's column data. MeasResults table is the first table and Moulds is the second table.
Here is how i get MeasResults table data;
using (LinqDataClassesDataContext dataContext = new
LinqDataClassesDataContext())
{
var query = from x in dataContext.MeasResults
where x.MoldID == cBMeasDBMID.SelectedValue.ToString()
group x by x.MeasId into grp
select grp.OrderByDescending(x => x.MeasId).First();
var result = query.OrderByDescending(x => x.MeasId).Take(5);
daGridLastMeas.AutoGenerateColumns = false;
daGridLastMeas.Columns["MeasId"].DataPropertyName = "MeasId";
daGridLastMeas.Columns["Date"].DataPropertyName = "Date";
daGridLastMeas.Columns["Plane"].DataPropertyName = "Plane";
daGridLastMeas.Columns["Position"].DataPropertyName = "Postn";
daGridLastMeas.DataSource = result;
}
And i tried to implement join function to get HeatCnt value from second table(Moulds).
using (LinqDataClassesDataContext dataContext = new
LinqDataClassesDataContext())
{
var query = from x in dataContext.MeasResults
where x.MoldID == cBMeasDBMID.SelectedValue.ToString()
join y in dataContext.Moulds on x.MoldID equals y.MID
group x by x.MeasId into grp
select grp.OrderByDescending(x => x.MeasId).First();
var result = query.OrderByDescending(x => x.MeasId).Take(5);
daGridLastMeas.AutoGenerateColumns = false;
daGridLastMeas.Columns["MeasId"].DataPropertyName = "MeasId";
daGridLastMeas.Columns["Date"].DataPropertyName = "Date";
daGridLastMeas.Columns["Heat"].DataPropertyName = "HeatCnt";
daGridLastMeas.Columns["Plane"].DataPropertyName = "Plane";
daGridLastMeas.Columns["Position"].DataPropertyName = "Postn";
daGridLastMeas.DataSource = result;
}
I know my problem is at select part of the query but i couldn't find out how to add y.HeatCnt to select query.
How can i do this?
NOTE
I've already studied the following thread about joining two tables, but it is not quite in same arrangement with way of my code.
Retrieving data from multiple tables using linq-to-sql
EDIT
(Heat Column should display 0)
I am bit confused about the data you want. But you can play arround with below solution and get your expected results.
var query =
from i in dataContext.Moulds
let p = dataContext.MeasResults.Where(p2 => i.MID == p2.MoldID).FirstOrDefault()
where i.MID == cBMeasDBMID.SelectedValue.ToString()
orderby i.MeasId descending
select new
{
MeasId = i.MID,
Date = p.Date,
Heat = i.Heat,
Plane = p.Plane,
Position = p.Position
};

Linq OrderBy String Property Length Has To Be in Select List

I am attempting to order the results of a Linq query by the length of a property and then by the property itself in order to order a string as an integer but the generated SQL is not ordering as I would expect it to.
I am joining multiple tables, filtering it down, selecting a DTO out with:
query = basequery.Select(s => new HeadersDTO
{
headerid = s.Header.id,
orderno = s.Header.orderno,
customer = s.Header.customer,
dateoforder = s.Header.dateoforder,
consignee = s.Location.name,
city = s.Location.name,
state = s.Location.state
}).Distinct();
Then trying to order by s.Header.orderno
query = query.OrderByDescending(x => x.orderno.Length).ThenByDescending(x => x.orderno)
.Skip(() => offset).Take(() => criteria.per_page);
This still orders it the normal way strings are ordered with first character taking precedence.
But if I select the x.orderno.Length out into it's own property and then order by that it works e.g.
query = basequery.Select(s => new HeadersDTO
{
ordernolength = s.Header.orderno.Length <---- added this
headerid = s.Header.id,
orderno = s.Header.orderno,
customer = s.Header.customer,
dateoforder = s.Header.dateoforder,
consignee = s.Location.name,
city = s.Location.name,
state = s.Location.state
}).Distinct();
query = query.OrderByDescending(x => x.ordernolength).ThenByDescending(x => x.orderno)
.Skip(() => offset).Take(() => criteria.per_page);
Is there a way to do this where I don't have to create a new property in the select list? I can add more information if needed.
Try to create a custom Comparer using IComparer where you do the Int32 check for this field. Here is an example for this:
Use own IComparer<T> with Linq OrderBy
Hope this helps

how to Merge results of two different entities in 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.

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.

Categories

Resources