I'm using the Mongo LINQ Driver for C#, works great.
Sorting a lot of properties but heres a problem I can't solve, its probably simple.
var identifierList = new []{"10", "20", "30"};
var newList = list.Where(x => identifierList.Contains(x.Identifier));
This is NOT supported ...
So I could do something like:
var newList = list.Where(x => x.Identifier == "10" || x.Identifier == "20" || x.Identifier == "30");
But since the list is variable ... how do I construct the above? Or are there even better alternatives?
The list is of type IQueryable<MyCustomClass>
For information ... this is used as a filter of alot of properties. In SQL I could have a parent -> child relationship. But as I can't as the parent for the main ID I need to take all the ID's out and then construct it like this.
Hopes this makes sense. If needed I will explain more.
To answer my own question ... The Mongo Sharp LINQ driver has an extension method called "In" which does exactly what I need.
They have however implemented it in 1.5 so we can use the old way like: https://jira.mongodb.org/browse/CSHARP-462
var list = new []{"10", "10"};
search.Where(x => list.Contains(x.Id));
But the version 1.5 package is not on nuget yet.
However, this should work with the "In" extension that comes as a special surprise with the mongo-csharp-driver.
search.Where(x => x.In(list));
var identifierList = new []{"10", "20", "30"};
var newList = list.ToList().Where(x => identifierList.Contains(x.Identifier));
You will just have to use List instead of Ienumerable (do that by using the .ToList())
If it doesn't work please add your list TYPE
Related
I've a linq query :
var NextWeekDate = DateTime.Now.AddDays(7);
var BirthData = db.EmployeeMasterAs
.Where(x => x.Emp_BirthDate >= CurrentDate)
.Select(x => new { x.Emp_BirthDate,
DaysRemaining = (NextWeekDate - x.Emp_BirthDate).Value.TotalDays
})
.OrderBy(x => x.Emp_BirthDate)
.ToList();
Note the element in Select() method, DaysRemaining = (NextWeekDate - x.Emp_BirthDate).Value.TotalDays, I want to get the difference between dates in days and save that to DaysRemaining, this query is not working and the exception that it throws :
DbArithmeticExpression arguments must have a numeric common type.
I don't know exactly how to achieve this, Any Ideas?
I think that LinqToSql does not support DateTime.Subtract. But you can use the preexisting function SqlMethods.DateDiffDay (https://msdn.microsoft.com/en-us/library/bb468730(v=vs.110).aspx)
Edit: SqlMethods is only intended for SQL Server. DbFunctions is the helper class to pick regardless of the database type.
Yep, Got it, So here is how it goes :
Performing arithmetic operations with Dates and Times is not supported in EF. EntityFramework cannot convert your code to SQL. Instead of that you can use DbFunctions.DiffDays( startExpression, endExpression) method:
db.EmployeeMasterAs
.Where(x => x.Emp_BirthDate >= CurrentDate)
.Select(x => new { x.Emp_BirthDate,
DaysRemaining = DbFunctions.DiffDays(x.Emp_BirthDate,NextWeek)
})
.OrderBy(x => x.Emp_BirthDate)
.ToList();
Furthermore : DbFunctions Functions methods are called canonical functions. And these are a set of functions, which are supported by all Entity Framework providers. These canonical functions will be translated to the corresponding data source functionality for the provider. Canonical functions are the preferred way to access functionality outside the core language, because they keep the queries portable.
I have this working Code
var h = db.MyTable.Include("Children").Include("Parent").ToList();
but when I add where condition
var h = db.MyTable.Include("Children").Include("Parent").Where(x => x.Country==Session["country"].ToString()).ToList();
it throws me an error
LINQ to Entities does not recognize the method 'System.Object get_item (System.String)' method , and this method cannot be translated into a store expression.
How can i rewrite it ? Im beginner :-)
Thank you
This is caused by your Where-Expression. You should only use variables in there or call methods that can be translated to SQL.
First, save your Session value in a variable:
var country = Session["country"].ToString();
Then use country in your Where-Expression.
MSDN provides a list of methods you can use inside LINQ to SQL expressions and how they are mapped to SQL functions.
try this:
var t = Session["country"].ToString();
var h = db.MyTable.Include("Children").Include("Parent").Where(x => x.Country==t).ToList();
only activities can be parsed into expression-tree that is supported by your provider
I am trying to perform an update using strongly-typed objects. For example,
public void setAppointmentPrefs(string UserName, IEnumerable<AppointmentInfo> info)
{
var query = new QueryDocument {{ "ProviderId", UserName}};
var update = Update.Set("Prefs",prefs); // prefs.toList() gives same error
// providerprefs initialized in constructor
providerprefs.Update(query, update);
}
I receive a compiler error saying:Error 14 The best overloaded method match for 'MongoDB.Driver.Builders.Update.Set(string, MongoDB.Bson.BsonValue)' has some invalid arguments
Obviously the Mongo driver will not let me update based on my own object (whether as IEnumerable or prefs.toList()), which seems a contrast from the way it permits me to insert or query with custom objects. Surely I am missing something obvious that would permit me to avoid deserializing, weakly typing then creating a generic BsonDocument!! TIA.
You can do an Update based on your own types! Have you tried using the typed Query and Update builders?
Try something like this:
var query = Query<AppointmentInfo>.EQ(i => i.ProviderId, userName);
var update = Update<AppointmentInfo>.Set(i => i.Prefs, info.Prefs);
Not sure I got the types and everything write from your partial code, but that should give you the general idea.
Let me know if you have any further questions.
I know this has been answered but I for one don't fully understand Roberts answer.
All I did is call the "ToBsonDocument()" method for it to except the object as a parameter
So:
customObject.ToBsonDocument()
If you have an array of objects inside a document:
var query = Query.EQ("_id", ObjectId.Parse(id.ToString()));
var update = Update.Push("ArrayOfObjects", customObject.ToBsonDocument());
collection.Update(query, update);
I'm trying to use Contains() in a simple query but it is failing, with the error :
Unable to create a constant value of type 'NewsletterApp.Models.NewsletterUser'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
Edit The intellisense actually directs me to use the NewsletterUser in Contains() -'(NewsletterUser item)'
I read that there were issues searching for an object using Contains() using EF with .NET 3.5, but I am using EF4.2 (also tried 4.1) with .NET 4.0 .
Code is below:
var db = new MyContext();
var newsletterUser = db.NewsletterUsers.Find(UserID);
var subscriberList = db.Subscribers
.Where(x => x.NewsletterList.ListOwner.NewsletterUsers.Contains(newsletterUser))
.ToList();
I suspect you want this
var db = new MyContext();
var newsletterUser = db.NewsletterUsers.Find(UserID);
var subscriberList = db.Subscribers
.Where(x => x.NewsletterList.ListOwner.NewsletterUsers
.Any(y => y.UserId == newsletterUser.UserId))
.ToList();
Any() checks for the existence of a item that fulfils the criteria specified in the lambda: "y => y.UserId == newsletterUser.UserId".
The exception you were getting: "Only primitive types ('such as Int32, String, and Guid') are supported in this context" is due to limitations set by LINQ to Entities. LINQ to Entities needs to resolve your query in a way that it can express to the database, and it can't do that with the Contains() method with anything other than a primitive type.
The thing is, the code you posted does run fine if you run it against an in memory collection (LINQ to Objects) - that's why it isn't flagged by the compiler.
Your query is wrong. Instead of comparing a property or field, you are comparing the whole object or entity, which can't be done in this manner.
Try the following code and it will work
var db = new MyContext();
var newsletterUser = db.NewsletterUsers.Find(UserID);
var subscriberList = db.Subscribers
.Where(x => x.NewsletterList.ListOwner.NewsletterUsers.UserId.Contains(newsletterUser.UserID))
.ToList();
I have an entity A with a simple navigation property B. For any given instance of A, we expect several related thousand instances of B.
There is no case where I call something like:
foreach(var x in A.B) { ... }
Instead, I'm only interested in doing aggregate operations such as
var statY = A.B.Where(o => o.Property == "Y");
var statZ = A.B.Where(o => o.CreateDate > DateTime.Now.AddDays(-1));
As far as I can tell, EF instantiates thousands of references to B and does these operations in memory. This is because navigation properties use EntityCollection. Instead, I'd like it to perform these queries at the SQL level if possible.
My current hunch is that Navigation Properties may not be the right way to go. I'm not attached to EF, so I am open to other approaches. But I'd be very interested to know the right way to do this under EF if possible.
(I'm using EF4.)
CreateSourceQuery seems to do the trick.
So my examples would now be:
var statY = A.B.CreateSourceQuery().Where(o => o.Property == "Y");
var statZ = A.B.CreateSourceQuery().Where(o => o.CreateDate > DateTime.Now.AddDays(-1));
There's one thing you should know. Members that derives from IQueryable<> are executed on the server, not in memory. Members which are derived from IEnumerable<> is executed in memory.
for example
var someEntities = db.SomeEntities; <-- returns an IQueryable<> object. no data fetched. SomeEntities table may contain thousands of rows, but we are not fetching it yet, we are just building a query.
someEntities = someEntities.Where(s => s.Id > 100 && s.Id < 200); <-- creates expression tree with where statement. The query is not executed yet and data is not fetched on the client. We just tell EF to perform a where filter when query will execute. This statement too returns an IQueryable<> object.
var entities = someEntities.AsEnumerable(); <-- here we tell EF to execute query. now entities will be fetched and any additional linq query will be performed in memory.
you can also fetch the data using foreach, calling ToArray() or ToList<>.
Hope you understand what I mean, and sorry for my english :)