Unable to create a constant value of type 'System.Object'. Only primitive types or enumeration types are supported in this context - asp.net-mvc

I have nurse and patient tables having a many to many relationship; thus, the third relationship table is nurse_patient consisting of n_id and p_id.
Once a nurse logins a session is created. I want to select all patients of this logged in nurse only. I tried the code below but it's giving the error shown in the title.
if (Session["LogedUserID"] != null)
{
int p = Convert.ToInt32(Session["LogedUserID"]);
var patients = db.patients.Where(a => a.nurse_patient.Select(x => x.n_id).Equals(p)).ToList();
return View(patients);
}

var patients = db.nurse_patient.Where(e => e.nurse.id == nid).Select(e => e.patient).ToList();
This solved it. Thanks

Related

Best Overloaded method match has some invalid arguments

I have two tables deal_outlet and vendors_outlet. I am trying to compare a list of outlet_id from deal_outlet table to vendor table but .contain method shows error has some invalid arguments. I really don't understand problem in this code.
public ActionResult Detail_of_deal(int id)
{
var d1 = db.deal_outlet.Where(x => x.outlet_id==id).ToList();
f_model.model4 = db.vendors_outlet.Where(x =>d1.Contains(x.outlet_id)).ToList();
var d = obj.detail_of_image(id,ref model);
return View(f_model);
}
Depending on the goal of the code you could try the following:
public ActionResult Detail_of_deal(int id)
{
var d1 = db.deal_outlet.Where(x => x.outlet_id==id).ToList();
f_model.model4 = db.vendors_outlet.AsEnumerable().Select(x => d1.Contains(x.outlet_id)).ToList();
var d = obj.detail_of_image(id,ref model);
return View(f_model);
}
That should make f_model.model4 a list of all the vendors_outlets that have a matching deal_outlet.id
The Linq Contains method returns true if the list contains the item passed in. You are asking to see if a list of deal_outlet objects contains an int, which obviously it won't.
Instead of projecting a collection of deal_outlets, project a list of integers:
var d1 = db.deal_outlet.Where(x => x.outlet_id==id).Select(x => x.outlet_id);
f_model.model4 = db.vendors_outlet.Where(x =>d1.Contains(x.outlet_id)).ToList();
But logically, that's the same as:
f_model.model4 = db.vendors_outlet.Where(x =>x.outlet_i==id)).ToList();
So it's not clear what you're trying to do.
EDIT
Based on your comments, I believe these are the queries you want:
i am trying to fetch list of outlet_id from deal_outlet table where deal_id equal to id,
var d1 = db.deal_outlet.Where(x => x.deal_id==id).ToList();
Now want to compare this list to vendor_outlet table and fetch those rows where outlet_id from deal_outlet table equals to outlet_id in vendor_outlet table
Get a list of ID's to match:
var ids = d1.Select(x => x.outlet_id).ToList();
And use Contains to see if the list contains any of the IDs from the related table:
f_model.model4 = db.vendors_outlet.Where(vo => ids.Contains(vo.outlet_id))
.ToList();

Return table records based on user role / table Join failing - linq query

I am building a MVC 5 (EF6) application that has a photographer table that's linked to the users table.
I identify a photographer by setting a role on the user account. The photographer table holds additional information not table. I have different types of users accessing the system.
I need to get the photographer table records based on the user being in the photographer role. I have the following solution but it comes back with the following error message when i try to access query result.
Unable to create a constant value of type 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole'. Only primitive types or enumeration types are supported in this context.
var photogpraherRole = db.Roles.Single(r => r.Name == "photographer");
var users = photogpraherRole.Users.ToList();
var photographersList =
from photographer in db.Photographers
join user in users on photographer.User.Id equals user.UserId
orderby photographer.Priority
select photographer;
foreach (var photographer in photographersList)
{
var photographerName = photographer.User.FirstName;
}
After some research and the help from #Shawn Yan, this is the solution i came up with.
var photographerRole = db.Roles.SingleOrDefault(m => m.Name == "photographer");
var disabledRole = db.Roles.SingleOrDefault(m => m.Name == "disabled");
var users = db.Users.Where(m => m.Roles.All(r => r.RoleId == photographerRole.Id && r.RoleId != disabledRole.Id)).ToList();
var photographersList =
from photographer in db.Photographers.ToList()
join user in users on photographer.User.Id equals user.Id
where photographer.Location == booking.location.Location
orderby photographer.Priority
select photographer;
var photographers = photographersList.ToList();

load navigation properties with filter for Entity Framework 4.3

Few days back I put a question regarding mapping two classes Message and MessageStatusHistory using EF. The mapping is going fine but I am facing some problems with the navigation property StatusHistory in class Message that relates it to MessageStatusHistory objects. I am loading the messages for one user only and want to the statuses pertaining to that user only. Like I would want to show if the user has marked message as read/not-read and when. If I use default loading mechanism like following it loads all the history related to the message irrespective of the user:
IDbSet<Message> dbs = _repo.DbSet;
dbs.Include("StatusHistory").Where(x=>x.MessageIdentifier == msgIdentifier);
To filter history for one user only I tried following trick:
IDbSet<Message> dbs = _repo.DbSet;
var q = from m in dbs.Include("StatusHistory")
where m.MessageIdentifier == msgIdentifier
select new Message
{
MessageIdentifier = m.MessageIdentifier,
/*OTHER PROPERTIES*/
StatusHistory = m.StatusHistory
.Where(x => x.UserId == userId).ToList()
};
return q.ToList();//THROWING ERROR ON THIS LINE
I am getting the error:
The entity or complex type 'MyLib.Biz.Message' cannot be constructed in a LINQ
to Entities query.
I have tried by commenting StatusHistory = m.StatusHistory.Where(x => x.UserId == userId).ToList() also but it has not helped.
Please help me in getting Messages with filtered StatusHistory.
EDIT:- above is resolved with this code:
var q = from m in _repository.DBSet.Include("Histories")
where m.MessageIdentifier == id
select new {
m.Id,/*OTHER PROPERTIES*/
Histories = m.Histories.Where(x =>
x.SenderId == userId).ToList()
};
var lst = q.ToList();
return lst.Select(m => new Message{
Id = m.Id, MessageIdentifier = m.MessageIdentifier,
MessageText = m.MessageText, Replies = m.Replies,
ReplyTo = m.ReplyTo, Histories = m.Histories, SenderId =
m.SenderId, SenderName = m.SenderName, CreatedOn = m.CreatedOn
}).ToList();
But if I try to include replies to the message with:
from m in _repository.DBSet.Include("Replies").Include("Histories")
I am getting error on converting query to List with q.ToList() for Histories = m.Histories.Where(x=> x.SenderId == userId).ToList().
About your EDIT part: You cannot use ToList() in a projection, just leave it an IEnumerable<T> and convert to a List<T> when you construct the Message. You also don't need to create two list objects, you can switch from the LINQ to Entities query to LINQ to Objects (the second Select) by using AsEnumerable():
var list = (from m in _repository.DBSet
where m.MessageIdentifier == id
select new {
// ...
Histories = m.Histories.Where(x => x.SenderId == userId)
})
.AsEnumerable() // database query is executed here
.Select(m => new Message {
// ...
Histories = m.Histories.ToList(),
// ...
}).ToList();
return list;
Be aware that Include has no effect when you use a projection with select. You need to make the properties that you want to include part of the projection - as you already did with select new { Histories.....

Getting a list of distinct entities projected into a new type with extra field for the count

I'm designing an interface where the user can join a publicaiton to a keyword, and when they do, I want to suggest other keywords that commonly occur in tandem with the selected keyword. The trick is getting the frequency of correlation alongside the properties of the suggested keywords.
The Keyword type (EF) has these fields:
int Id
string Text
string UrlString
...and a many-to-many relation to a Publications entity-set.
I'm almost there. With :
var overlappedKeywords =
selectedKeyword.Publications.SelectMany(p => p.Keywords).ToList();
Here I get something very useful: a flattened list of keywords, each duplicated in the list however many times it appears in tandem with selectedKeyword.
The remaining Challenge:
So I want to get a count of the number of times each keyword appears in this list, and project the distinct keyword entities onto a new type, called KeywordCounts, having the same fields as Keyword but with one extra field: int PublicationsCount, into which I will populate the count of each Keyword within overlappedKeywords. How can I do this??
So far I've tried 2 approaches:
var keywordCounts = overlappingKeywords
.Select(oc => new KeywordCount
{
KeywordId = oc.Id,
Text = oc.Text,
UrlString = oc.UrlString,
PublicationsCount = overlappingKeywords.Count(ok2 => ok2.Id == oc.Id)
})
.Distinct();
...PublicationsCount is getting populated correctly, but Distinct isn't working here. (must I create an EqualityComarer for this? Why doesn't the default EqualityComarer work?)
var keywordCounts = overlappingKeywords
.GroupBy(o => o.Id)
.Select(c => new KeywordCount
{
Id = ???
Text = ???
UrlString = ???
PublicationsCount = ???
})
I'm not very clear on GroupBy. I don't seem to have any access to 'o' in the Select, and c isn't comping up with any properties of Keyword
UPDATE
My first approach would work with a simple EqualityComparer passed into .Distinct() :
class KeywordEqualityComparer : IEqualityComparer<KeywordCount>
{
public bool Equals(KeywordCount k1, KeywordCount k2)
{
return k1.KeywordId== k2.KeywordId;
}
public int GetHashCode(KeywordCount k)
{
return k.KeywordId.GetHashCode();
}
}
...but Slauma's answer is preferable (and accepted) because it does not require this. I'm still stumped as to what the default EqualityComparer would be for an EF entity instance -- wouldn't it just compare based on primary ids, as I did above here?
You second try is the better approach. I think the complete code would be:
var keywordCounts = overlappingKeywords
.GroupBy(o => o.Id)
.Select(c => new KeywordCount
{
Id = c.Key,
Text = c.Select(x => x.Text).FirstOrDefault(),
UrlString = c.Select(x => x.UrlString).FirstOrDefault(),
PublicationsCount = c.Count()
})
.ToList();
This is LINQ to Objects, I guess, because there doesn't seem to be a EF context involved but an object overlappingKeywords, so the grouping happens in memory, not in the database.

How to join multiple tables using LINQ-to-SQL?

I'm quite new to linq, so please bear with me.
I'm working on a asp.net webpage and I want to add a "search function" (textbox where user inputs name or surname or both or just parts of it and gets back all related information). I have two tables ("Person" and "Application") and I want to display some columns from Person (name and surname) and some from Application (score, position,...). I know how I could do it using sql, but I want to learn more about linq and thus I want to do it using linq.
For now I got two main ideas:
1.)
var person = dataContext.GetTable<Person>();
var application = dataContext.GetTable<Application>();
var p1 = from p in Person
where(p.Name.Contains(tokens[0]) || p.Surname.Contains(tokens[1]))
select new {Id = p.Id, Name = p.Name, Surname = p.Surname}; //or maybe without this line
//I don't know how to do the following properly
var result = from a in Application
where a.FK_Application.Equals(index) //just to get the "right" type of application
//this is not right, but I don't know how to do it better
join p1
on p1.Id == a.FK_Person
2.) The other idea is just to go through "Application" and instead of "join p1 ..." to use
var result = from a in Application
where a.FK_Application.Equals(index) //just to get the "right" type of application
join p from Person
on p.Id == a.FK_Person
where p.Name.Contains(tokens[0]) || p.Surname.Contains(tokens[1])
I think that first idea is better for queries without the first "where" condition, which I also intended to use. Regardless of what is better (faster), I still don't know how to do it using linq. Also in the end I wanted to display / select just some parts (columns) of the result (joined tables + filtering conditions).
I really want to know how to do such things using linq as I'll be dealing also with some similar problems with local data, where I can use only linq.
Could somebody please explain me how to do it, I spent days trying to figure it out and searching on the Internet for answers.
var result = from a in dataContext.Applications
join p in dataContext.Persons
on p.Id equals a.FK_Person
where (p.Name.Contains("blah") || p.Surname.Contains("foo")) && a.FK_Application == index
select new { Id = p.Id, Name = p.Name, Surname = p.Surname, a.Score, a.Position };
Well as Odrahn pointed out, this will give you flat results, with possibly many rows for a single person, since a person could join on multiple applications that all have the same FK. Here's a way to search all the right people, and then add on the relevant application to the results:
var p1 = from p in dataContext.Persons
where(p.Name.Contains(tokens[0]) || p.Surname.Contains(tokens[1]))
select new {
Id = p.Id, Name = p.Name, Surname = p.Surname,
BestApplication = dataContext.Applications.FirstOrDefault(a => a.FK_Application == index /* && ???? */);
};
Sorry - it looks like this second query will result in a roundtrip per person, so it clearly won't be scalable. I assumed L2S would handle it better.
In order to answer this properly, I need to know if Application and Person are directly related (i.e. does Person have many Applications)? From reading your post, I'm assuming that they are because Application seems to have a foreign key to person.
If so, then you could create a custom PersonModel which will be populated by the fields you need from the different entities like this:
class PersonModel
{
string Name { get; set; }
string Surname { get; set; }
List<int> Scores { get; set; }
List<int> Positions { get; set; }
}
Then to populate it, you'd do the following:
// Select the correct person based on Name and Surname inputs
var person = dataContext.Persons.Where(p => p.Name.Contains("firstname") || p.Name.Contains("surname")).FirstOrDefault();
// Get the first person we find (note, there may be many - do you need to account for this?)
if (person != null)
{
var scores = new List<int>();
var positions = new List<int>();
scores.AddRange(person.Applications.Select(i => i.Score);
positions.AddRange(person.Applications.Select(i => i.Position);
var personModel = new PersonModel
{
Name = person.Name,
Surname = person.Surname,
Scores = scores,
Positions = positions
};
}
Because of your relationship between Person and Application, where a person can have many applications, I've had to account for the possibility of there being many scores and positions (hence the List).
Also note that I've used lambda expressions instead of plain linqToSql for simple selecting so that you can visualise easily what's going on.

Resources