This piece of code keep making this error. :
Unable to create a constant value of type 'Repository.DBModel.Subscriber'. Only primitive types or enumeration types are supported in this context.
I've Changed it a few times but it keeps coming up with this Error.
using (SubscriberDBHandler db = new SubscriberDBHandler())
{
IEnumerable <Subscriber> NewSubscribers = Subscribers
.Where(sub => db.Subscriber
.Any(aSub => !aSub.Email.Equals(sub.Email)));
List<Subscriber> updateSubscribers = db.Subscriber
.Where(dbSub => Subscribers
.Any(lSub => lSub.Email
.Equals(dbSub.Email))).ToList();
if(NewSubscribers.Count() >= 1)
{
db.Subscriber.AddRange(NewSubscribers);
}
updateSubscribers.ForEach(aSub => aSub.State = Subscribers
.FirstOrDefault(sub => sub.Email
.Equals(aSub.Email)).State ?? "Error" );
db.SaveChanges();
}
I'd greatly appreciate if someone could point out my error or come up with a more efficient way to do this.
In advance thanks for your time and help.
I know there are a few post with this error out there but when reading them I can't figure out how they relate to my problem. so I'm sorry if this is a common mistake and others have provided a solution
The object Subscribers is a List<Subscriber>
I don't seem to be able to find the line but. the stack trace does contain this.
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at Repository.SubScribRepository.AddOrUpdateSubscribers(List1 Subscribers)
You use a local collection, Subscribers, directly in a LINQ statement. But these objects can't be translated into SQL. There are only mappings from primitive types to database types.
I'd suggest you use
var emails = Subscribers.Select(s => s.Email).ToList();
And proceed by using these strings (i.e. primitive values) in Contains statements like:
var newSubscribers = db.Subscriber
.Where(dbSub => !emails.Contains(dbSub.Email))
.ToList();
var updateSubscribers = db.Subscriber
.Where(dbSub => emails.Contains(dbSub.Email))
.ToList();
Changing updateSubscribers to an IEnumerable will prevent this error
Related
This piece of code keep making this error. :
Unable to create a constant value of type 'Repository.DBModel.Subscriber'. Only primitive types or enumeration types are supported in this context.
I've Changed it a few times but it keeps coming up with this Error.
using (SubscriberDBHandler db = new SubscriberDBHandler())
{
IEnumerable <Subscriber> NewSubscribers = Subscribers
.Where(sub => db.Subscriber
.Any(aSub => !aSub.Email.Equals(sub.Email)));
List<Subscriber> updateSubscribers = db.Subscriber
.Where(dbSub => Subscribers
.Any(lSub => lSub.Email
.Equals(dbSub.Email))).ToList();
if(NewSubscribers.Count() >= 1)
{
db.Subscriber.AddRange(NewSubscribers);
}
updateSubscribers.ForEach(aSub => aSub.State = Subscribers
.FirstOrDefault(sub => sub.Email
.Equals(aSub.Email)).State ?? "Error" );
db.SaveChanges();
}
I'd greatly appreciate if someone could point out my error or come up with a more efficient way to do this.
In advance thanks for your time and help.
I know there are a few post with this error out there but when reading them I can't figure out how they relate to my problem. so I'm sorry if this is a common mistake and others have provided a solution
The object Subscribers is a List<Subscriber>
I don't seem to be able to find the line but. the stack trace does contain this.
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at Repository.SubScribRepository.AddOrUpdateSubscribers(List1 Subscribers)
You use a local collection, Subscribers, directly in a LINQ statement. But these objects can't be translated into SQL. There are only mappings from primitive types to database types.
I'd suggest you use
var emails = Subscribers.Select(s => s.Email).ToList();
And proceed by using these strings (i.e. primitive values) in Contains statements like:
var newSubscribers = db.Subscriber
.Where(dbSub => !emails.Contains(dbSub.Email))
.ToList();
var updateSubscribers = db.Subscriber
.Where(dbSub => emails.Contains(dbSub.Email))
.ToList();
Changing updateSubscribers to an IEnumerable will prevent this error
Why does:
var allShapes = _context.AttributeValuesLibraries.Where(x => x.AttNameID.Equals(1)).Select(y => y);
work, but I get the error "Unable to create a constant value of type 'System.Object'. Only primitive types or enumeration types are supported in this context" when I exclude the Select() like:
var allShapes = _context.AttributeValuesLibraries.Where(x => x.AttNameID.Equals(1));
Is there another way to write this query so it makes more sense? I just played with the query to make it work.
Thanks in advance!
Try this:
var allShapes = _context.AttributeValuesLibraries.Where(x => x.AttNameID == 1);
It really depends on your Linq provider.
In my application I have Lecturers and they have list of Courses they can teach and when I'm deleting a course I want to remove connection to lecturers. Here's the code:
public void RemoveCourse(int courseId)
{
using (var db = new AcademicTimetableDbContext())
{
var courseFromDb = db.Courses.Find(courseId);
var toRemove = db.Lecturers
.Where(l => l.Courses.Contains(courseFromDb)).ToList();
foreach (var lecturer in toRemove)
{
lecturer.Courses.Remove(courseFromDb);
}
db.SaveChanges();
}
}
but it doesn't work. I get
NotSupportedException: Unable to create a constant value of type Course. Only primitive types or enumeration types are supported in this context.
What am I doing wrong?
You can't use Contains with non-primitive values. Do
Where(l => l.Courses.Select(c => c.CourseId).Contains(courseId)
(or the Id field you use).
If you are using a DbContext, you can query the .Local collection, and the == operator will work also with objects:
public void RemoveCourse(int courseId)
{
using (var db = new AcademicTimetableDbContext())
{
var courseFromDb = db.Courses.Find(courseId);
db.Lecturers.Load() //this is optional, it may take some time in the first load
//Add .Local to this line
var toRemove = db.Lecturers.Local
.Where(l => l.Courses.Contains(courseFromDb)).ToList();
foreach (var lecturer in toRemove)
{
lecturer.Courses.Remove(courseFromDb);
}
db.SaveChanges();
}
}
The .Local is an ObservableCollection, so you can compare anything you like inside it (not limited to SQL queries which don't support object comparison). Just to make sure you get all your objects in the .Local collection you can call the db.Lecturers.Load() method before calling .Local, which brings all database entries into the Local collection.
The Courses collection of below line should be null or empty.
var toRemove = db.Lecturers
.Where(l => l.Courses.Contains(courseFromDb)).ToList();
This can also happen when you pass a Func<T, bool> to Where() as a way to write a dynamic condition like here here
For some reason the delegate can't be translated to SQL.
You cannot compare complex type, if you have not specified what you mean for equality.
As exception detail says, you need to check primitive values (like Integer in your case).
And better to use Any() method instead.
var toRemove = db.Lecturers
.Where(l => l.Courses.Any(p=>p.Id == courseFromDb.Id)).ToList();
I can't seem to figure out how to compare boolean values in a C# lambda expression for EF4. I've tried:
cl.Where(c => c.Received == false);
and this:
cl.Where(c => !c.Received);
and this:
cl.Where(c => c.Received.Equals(false));
but I keep getting this error:
Exception Details: System.NotSupportedException: Unable to create a constant value
of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid')
are supported in this context.
After spending a good amount of time researching this I'm still missing something. I'm fairly new to Lambdas so pointers would be appreciated.
Edit2: more code re:comment
int bar = 42;
var cl = db.foo.Where(c => c.baz.Equals(bar));
//codez (just an if statement)
cl.Where(c => c.Received == false).OrderByDescending(c => c.dateAdded);
That's it. Even if I remove the orderby it still doesn't work
Edit3:
Solution:
int bar = 42;
var cl = db.foo.Where(c => c.baz == bar);
cl.Where(c => c.Received == false).OrderByDescending(c => c.dateAdded);
The issue is most likely in the c.baz.Equals(bar) line. If you change it to
var cl = db.foo.Where(c => c.baz.Equals(bar)).ToList();
you should see the exception thrown on that line, because you force evaluation of the IQueryable<T>.
Instead of comparing objects, you should compare their IDs, like this:
(edited to reflect the conversation in the comments and changes to the OP)
var cl = db.foo.Where(c => c.baz == bar.id);
What is the type of Received ? Where close need a predicate(a function that return Boolean) in order to act upon every element in the list and return those that satisfy the condition. From the error message it seems the Received in not primitive type. You need to cast it to boolean if you for sure know its boolean.
I realized that for some odd reason you can't chain the .Where() after the .Select(), so I came up with this.
var eventCalendar = db.EventCalendars.Where(q => q.Date == e.Day.Date);
if (!isLogged)
{
eventCalendar = eventCalendar.Where(q => q.ClientFlag == true);
}
eventCalendar = eventCalendar.Select(q => q.EnvironmentId).Distinct();
but now I get and error at the .Select
"Cannot implicitly convert type 'System.Linq.IQueryable<short>' to 'System.Linq.IQueryable<IT_Portal.EventCalendar>'. An explicit conversion exists (are you missing a cast?)"
What am I doing wrong? To put it simply, I just want to be able to grab Distinct Environment ID from the Calendar Event table so that I can notify users if there is an event occurring that day on a specific environment. Finally if the user is not logged in, get only Environment Id from events that are marked to be displayed for client (ClientFlag).
Your last line is the problem. You're trying to re-use a local variable that is a different type than you're assigning to it. You just need to change it slightly:
var eventCalendarEnvironmentIds =
eventCalendar.Select(q => q.EnvironmentId).Distinct();
You need a new variable.
var environmentIDs = eventCalendar.Select(q => q.EnvironmentId).Distinct();
By selecting Select(q => q.EnvironmentId) you are actually selecting the EnvironmentId and not the eventCalenderObject.
Try changing:
var eventCalendar = db.EventCalendars.Where(q => q.Date == e.Day.Date);
to:
// I specify IQueryable, you can use 'var' - you simply need to change the variable name
IQueryable eventQuery = db.EventCalendars.Where(q => q.Date == e.Day.Date);
Then, selecting:
var eventCalendar = eventQuery.Select(q => q.EnvironmentId).Distinct();
Sometimes, when you continue to use var, you may lose sight of the data type. You should use the actual data type as often as you can. Getting caught in the trap of using var is not a good practice, IMO.