passing linq anonymous result to iqueryable object for another query - c#

I have two tables (tbPerson and tbDataLog) where I need to return Id from one table (tbPerson) after checking certain conditions on both. After this, this result should be passed to another query. My first query returns the Id (primary key of a table) successfully and I need to pass these ids to another query so that it return me data based upon these Id. I also has an IQueryable type base object to check certain conditions to fetch data.
IQueryable<tbPerson> dataset
and I cannot changes this from Iqueryable to other as it will break other part of the code)
My first linq statement:
public static IQueryable<LogResults> GetResultsForYes()
{
Databasename ents = new Databasename();
var ids = (from f in ents.tbPerson
join g in ents.tbDataLog
on f.InfoID equals g.RefId
where g.Tag == "subscribed" && g.OldValue == "No" && g.Action == "Modified"
select new LogResults { _LogID = f.Id }).OrderBy(x => x._LogID);
return ids;
}
public class LogResults
{
public int _LogID { get; set; }
}
I access my result something like this where I can see in debugger all the Ids.
IQueryable<LogResults> log = GetResultsForYes();
Problem comes, when I tried to get records from tbPerson based upon these returned Id.
dataset=log.where(x=>x._LogID != 0);
I get this error:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists(are you missing a cast)?
Any suggestions or some other good approach is welcome.

I love this thing about stackoverflow. when we write questions we force our brain to think more deeply and after 30 mins of posting this question, I solved it in a simple way. Sometimes we overcomplicated things!
var ids = (from f in ents.tbPerson
join g in ents.tbDataLog
on f.InfoID equals g.RefId
where g.Tag == "subscribed" && g.OldValue == "No" && g.Action == "Modified"
select new { f.Id }).ToArray();
var allId = ids.Select(x => x.Id).ToArray();
dataset = dataset.Where(x => allId.Contains(x.Id));
#ankit_sharma : I have not tested yours but will give a try and come back to you. Thanks for giving time and effort.

IQueryable<tbPerson> dataset=log.where(x=>x._LogID != 0);
The result of log.where(x=>x._LogID != 0) is an IQueryable<LogResults>, and you are trying to assign this result to dataset of type IQueryable<tbPerson>, two diferent types.
EDIT:
I see you make a join to get the tbPerson ids, and then you do a second query to get the persons. You could get the persons in the first join.
I just modify your code:
IQueryable<tbPerson> persons = from person in ents.tbPerson
join g in ents.tbDataLog
on person.InfoID equals g.RefId
where g.Tag == "subscribed" && g.OldValue == "No" && g.Action == "Modified"
select person;

Related

Update IQueryable result before using as join in next query

I need to use Linq to Entity Framework to query a LOCATION table to get the record of the location code with the MAX effective date, then use that result as a join in the next query.
I BELIEVE I need to do convert before the IQueryable is used, because I have that last clause in the second query where I want to exclude records where the FLOOR code is in the excludedSchools list. That excludedSchools list will have the newLocationCode in it.
So, I need to update the values in the IQueryable result before I use it. Can I do this? Here is my code:
using (var db = new TheContext())
{
IQueryable<LocationTable> locatinWithMaxEffDate =
(from lc in db.LocationTable
where lc.EFF_STATUS == "A" && lc.EFFDT <= DateTime.Now
group lc by lc.LOCATION into g
select g.OrderByDescending(x => x.EFFDT).FirstOrDefault()
);
foreach (var location in locatinWithMaxEffDate.ToList())
{
string newLocationCode;
if(codeMappingDictionary.TryGetValue(location.FLOOR, out newLocationCode))
{
// how do I update locatinWithMaxEffDate FLOOR value
// with newLocationCode so it works in the query below?
location.FLOOR = newLocationCode;
}
}
var query =
(from fim in db.PS_PPS_FIM_EE_DATA
join mloc in locatinWithMaxEffDate on fim.LOCATION equals mloc.LOCATION
where
fim.EMPL_STATUS == PsPpsFimEeData.EmployeeStatusValues.Active
&& fim.AUTO_UPDATE == PsPpsFimEeData.AutoUpdateValues.Enabled
&& includeJobCodes.Contains(fim.JOBCODE)
&& !excludedSchools.Contains(mloc.FLOOR)
select new PpsAdministratorResult
{
SchoolId = mloc.FLOOR,
Login = fim.OPRID,
EmployeeId = fim.EMPLID,
}
With the code above, the locatinWithMaxEffDate does not have the updated FLOOR values. I can see why this is, but can't seem to fix it.
So far, I have tried introducing another list to ADD() the new location record to, then casting that as an IQueryable, but I get an error about primitive vs concrete types.
I decided to make things easier on myself. Since both sets of data are very small (fewer than 1000 records each) I call take the entire set of data as an annonymous type:
using (var db = new TheContext())
{
IQueryable<LocationTable> locatinWithMaxEffDate =
(from lc in db.LocationTable
where lc.EFF_STATUS == "A" && lc.EFFDT <= DateTime.Now
group lc by lc.LOCATION into g
select g.OrderByDescending(x => x.EFFDT).FirstOrDefault()
);
var query =
(from fim in db.PS_PPS_FIM_EE_DATA
join mloc in locatinWithMaxEffDate on fim.LOCATION equals mloc.LOCATION
where
fim.EMPL_STATUS == PsPpsFimEeData.EmployeeStatusValues.Active
&& fim.AUTO_UPDATE == PsPpsFimEeData.AutoUpdateValues.Enabled
&& includeJobCodes.Contains(fim.JOBCODE)
select new PpsAdministratorResult
{
SchoolId = mloc.FLOOR,
Login = fim.OPRID,
EmployeeId = fim.EMPLID,
}
}
Then, just work with the two objects:
List<PpsAdministratorResult> administratorList = new List<PpsAdministratorResult>();
foreach (var location in query.ToList())
{
string newLocationCode;
if(schoolCodeMappings.TryGetValue(location.SchoolId, out newLocationCode)) // && newLocationCode.Contains(location.LOCATION))
{
location.SchoolId = newLocationCode;
}
if( !excludedSchools.Contains(location.SchoolId) )
{
administratorList.Add(location);
}
}
Now, I have the list I want.

How to Link two IDs from different classes in MVC5 to display certain information

I am trying to link up the RestaurantId in the RestaurantReservationEventsTbl with the RestaurantID in the RestaurantTbl to display reservations that are only made for the currently logged in restaurant.
I am receiving the following error in my code operator == cannot be applied to operands of type int and iqueryable int
Here is what I am doing in my home controller
var RestaurantIDRestaurantTbl = from r in db.Restaurants select r.RestaurantID;
//var listOfRestaurantsReservations = db.RestaurantReservationEvents.ToList();
var listOfRestaurantsReservations = db.RestaurantReservationEvents.Where(x => x.RestaurantID == RestaurantIDRestaurantTbl).ToList();
//return View(restaurants.Where(x => x.RestaurantEmailAddress == UserEmail).ToList());
//create partial view called _RestaurantReservation
return PartialView("_RestaurantReservations", listOfRestaurantsReservations);
You have to change your code to materialize the restaurantIds like this:
var RestaurantIDRestaurantTbl = (from r in db.Restaurants
select r.RestaurantID).ToList();
Then you may change the code as below for the comparison to work:
var listOfRestaurantsReservations = db.RestaurantReservationEvents.Where(x => RestaurantIDRestaurantTbl.Contains(x.RestaurantID)).ToList();
Anyway this is not the best solution. I will write another example for you, just try this example if it is working or not and let me know for the result.
I would considering changing the code as below to be much more efficient:
var listOfRestaurantsReservations = (from r in db.Restaurants
join e in db.RestaurantReservationEvents
on r.RestaurantID equals e.RestaurantID
//where r.RestaurantID == something //if where condition needed
select e).ToList();
If your tables are not connected with foreignkeys please consider to read this documentation here to make a better structure of the tables since they are related to each-other.
If your tables are related as in documentation article you might have something like that:
var RestaurantIDRestaurantTbl = db.Restaurants.SingleOrDefault(x => x.RestaurantID == something);
if(RestaurantIDRestaurantTbl != null)
{
var listOfRestaurantsReservations = RestaurantIDRestaurantTbl.RestaurantReservationEvents.ToList();
}
{
// This will give you a list of IDs
var RestaurantIDRestaurantTbl = db.Restaurants
.Select(p => p.RestaurantID)
.ToList();
// Using .Any() is a better choice instead of .Contains()
// .Contains is used to check if a list contains an item while .Any will look for an item in a list with a specific ID
var listOfRestaurantsReservations = db.RestaurantReservationEvents
.Where(p => RestaurantIDRestaurantTbl.Any(r => r.pRestaurantID == p))
.ToList();
}

Make a LINQ query dynamic to bring back all rows or only rows with a link to a lookup table?

I have a query that returns a list of currencies and joins to a lookup table. The result is then put into a class object (which works fine):
var queryforobject = from x in db.CurrencyExchangeRates.AsNoTracking()
join c in db.CurrencyTypes.AsNoTracking() on x.CurrencyTypeID equals c.ID
orderby x.ID
select new CurrencyExchangeRateObject
{
ID = x.ID,
CurrencyID = c.ID,
Currency = c.Description,
ExchangeRate = x.ExchangeRate,
LastEditedDate = x.LastEditedDate,
LastEditedBy = x.LastEditedBy,
Active = x.Active
};
I want to make this more dynamic, so if no CurrencyTypeID is supplied then it will return the full list (as it does already) - otherwise if a CurrencyTypeID is supplied it will only show where X.CurrencyTypeID = ID.
Something along the lines of an inline if?
There are a few options for filtering the query based on CurrencyTypeID if a search value (named currencyTypeID in this answer) is supplied, but return all data if no currencyTypeID is supplied.
First option: You could add a where clause to your existing query expression. The WHERE clause below will return every record in the data set if null is passed in for the currencyTypeID variable, otherwise it will filter the results.
from x in db.CurrencyExchangeRates.AsNoTracking()
join c in db.CurrencyTypes.AsNoTracking() on x.CurrencyTypeID equals c.ID
where (currencyTypeID == null || x.CurrencyTypeID == currencyTypeID)
orderby x.ID
select new CurrencyExchangeRateObject {
ID = x.ID,
CurrencyID = c.ID,
Currency = c.Description,
ExchangeRate = x.ExchangeRate,
LastEditedDate = x.LastEditedDate,
LastEditedBy = x.LastEditedBy,
Active = x.Active
};
Alternatively: Since queryforobject is of type IQueryable<T>, you can use LINQ's fluent API to append a WHERE clause to the query inside an if statement. You need to be more careful about timing on this one though as it needs to be done before you force evaluation of the IQueryable with a foreach loop, .ToList(), .Select() or other LINQ methods that force evaluation.
if(currencyTypeID != null)
queryforobject = queryforobject.Where(cerObj => cerObj.CurrencyID == currencyTypeID);

Join tables in NHibernate without mapping

I have the following two objects:
User
class User {
public int role;
}
Role
class Role {
public int id;
public string name;
}
be note that role property inside User is int and not Role, that's our limitations.
I want to join between all the users and each of his role. In the mapping objects there is no reference as you can understand, just a simple type (int).
How do I do that join statement?
It's called a theta join:
var a = (from u in session.Query<User>()
from r in session.Query<Role>()
where u.role == r.id
select new { u.Username, Role = r.name }).ToList();
Assuming you have a Username property on the User class.
Yes, this "theta join" (as I just learned this term) is very handy and let's us not worry about putting in pointless mapping relationships.
WARNING HOWEVER IN USING THIS!!! This tripped me up a lot.
Adding to the above example...
var list = new List<int>( { 2, 3 } ); // pretend in-memory data from something.
var a =
(from u in session.Query<User>()
from x in list
from r in session.Query<Role>()
where u.role == r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name }).ToList();
THIS WILL BOMB with some NotSupported exception.
The trick is that anything coming from NHibernate Session must come LAST. So this alteration WILL work:
var a =
(from x in list
from u in session.Query<User>()
from r in session.Query<Role>()
where u.role == r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name }).ToList();
And and BTW, you can use join as well, however you have to make sure if you have any nullable data types, that you use the .Value if you are joining to something not-nullable.
var a =
(from x in list
from u in session.Query<User>()
join r in session.Query<Role>() on u.role equals r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name }).ToList();
And while we're at it, let's say you have a method that has some dynamic condition. In this example the 'list' which could be a list of roles to filter by, but don't filter at all if the list is not there. Well, if you do the .ToList() then you are causing this query to execute immediately. But instead you can add a condition and then execute it later:
var a =
from u in session.Query<User>()
join r in session.Query<Role>() on u.role equals r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name, RoleID = r.id }; // Adding the Role ID into this output.
if (list != null) // assume if the list given is null, that means no filter.
{
a = a.Where(x => list.Contains(x.RoleID));
// WARNING. Unfortunately using the "theta" format here will not work. Not sure why.
}
var b = a.ToList(); // actually execute it.
var c = a.Select(x => new { x.Username, x.Role }).ToList() // if you insist on removing that extra RoleID in the output.
One last thing.. Sometimes some simple logic will fail when executed in the select new { .. } part. I don't have an explanation. In our case the logic was just converting a DB value of a uint to an Enumerator of a model. But to get around that, I just avoided doing that conversion while reading the data but saved the value. Then in a later step, after the data was loaded, I just did the conversion in another LINQ statement.
DISCLAIMER: While I wrote many of these things all the past several weeks, I did not put this code into my compiler to verify 100%.

How to get back result from a session

Work on entity frame work vs2010
After execute my linq query get a list of records ,want to put this record in session .Now from session Want to get back my record list ,what to do how to get back record from a session
Linq query
public IEnumerable GetSearchUserGroupPermissionData(int userID = 0)
{
var query = from p in this.Context.CmnPermissionGroupUsers
join q in this.Context.CmnPermissionGroups on p.PermissionGroupID equals q.PermissionGroupID
join r in this.Context.CmnPermissionGroupDocs on p.PermissionGroupID equals r.PermissionGroupID
join s in this.Context.CmnUserInfoes on p.UserID equals s.UserID
join t in this.Context.CmnDocLists on r.DocListID equals t.DocListID
//join u in this.Context.CmnModuleFormCompanies on t.ModuleID equals u.ModuleID
//join v in this.Context.CmnModuleLists on u.ModuleID equals v.ModuleID
//join w in this.Context.CmnFormLists on u.FormID equals w.FormID
where p.IsDeleted == false
select new
{
RecordID = p.PermissionGroupUserRecordID,
s.UserID,
s.UserFirstName,
q.PermissionGroupName,
p.EffectiveDate,
p.StatusID,
t.DocListID,
t.DocName,
t.ModuleID,
// v.ModuleName,
// u.FormID,
// t.FormName,
// w.FormName,
t.ParentID,
t.Sequence,
t.IsApprovalRequired,
t.CompanyCategoryID,
t.DocTypeID
//p.CreateBy,
//p.CreateOn,
//p.CreatePc,
//p.UpdateBy,
//p.UpdateOn,
//p.UpdatePc,
//p.IsDeleted,
//p.DeleteBy,
//p.DeleteOn,
//p.DeletePc,
//p.Transfer
};
return query.WhereIf(userID != 0, w => w.UserID == userID).ToList();
}
Put result in session
Session["UserPermission"] = new PermissionGroupUserController().GetSearchUserGroupPermissionData(objEntity.UserID);
Now ,want to get back the record set from session.bellow foreach syntax area as a item contain each row all properties and values but can not assign in a variable just like bellow ,why can not assign an AnonymousType variable value to a variable.
var o = Session["UserPermission"] as IEnumerable; //use casting
foreach (var area in o)
{
//int a = area.UserID;
}
Note:sabove syntax how me error
message:foreach statement cannot operate on variables of type 'object'
because 'object' does not contain a public definition for
'GetEnumerator'
If have any query please ask.
Did you try typecasting oto IEnumerable?
Apart from that, in your foreach loop, you have to use dynamic instead of var. This is required because your type is anonymous.
But i would still strongly suggest you to use normal types instead of Anonumous ones atleast for two reasons
Code reusability.
Better code readability.

Categories