I made a SqlDependency service in my application. It works perfectly when I type the queries by hand but I cannot include wildcards (I don't really know why).
For example:
//Using this SqlCommand will work
new SqlCommand("SELECT [employees].[name] FROM [dbo].[employees]", sqlNotificationConn)
//But this one won't
new SqlCommand("SELECT [employees].* FROM [dbo].[employees]", sqlNotificationConn)
//And this one won't either
new SqlCommand("SELECT * FROM [dbo].[employees]", sqlNotificationConn)
So basically, I want to get my DbContext to generate a full SELECT command with every fields it deals with.
In Linq 2 SQL, I used this service using dbContext.GetCommand(.....);
In EF 4.0 (or was it 4.1?), I used dbContext.employee.ToTraceString();
But in EF 4.4, I can't find anything to generate that SELECT query string....
With DbContext (DbQuery) it is as simple as:
query.ToString()
With ObjectContext (ObjectQuery):
((ObjectQuery)query).ToTraceString()
By the way, query can be any expression based on a DbSet (or ObjectSet, respectively). So something like dbContext.employee.Where(e => e.Name == "Gates").ToString() will also show the generated SQL query.
A LINQ statement that forces execution, like ToList(), Single(), FirstOrDefault(), etc, creates a new object and ToString() will return the object's type name.
ToTraceString() is still in EF, same place it always was. However, it's on ObjectQuery, not DbQuery. Having said that, I've never seen the SQL Server provider for EF use *; it always uses discrete fields in SQL.
Related
getting this error on where clause.
trying to fetch records from sql server with linQ query in entity framework.
var Stud = contextSchool.Student.Where(x => x.STDNT_ID == lstStudent[i].StudentID).FirstOrDefault();
if i store value of list in a variable and then use in where clause, it works but not with list.
complete error:
linQ to entities does not recognize the method Models.Repository.Student get_Item(Int32)' method, and this method cannot be translated into a store expression.
i also get this error on some other projects, the problem is that u cant use methods like get_Item or f.e. AddDays() in ur linq command.
So u kinda have to play around it.
U have to create an object (list, or whatever) before ur linq command and fill it with the data u need (per methods) and use the variable in ur linq command.
It is easy to do a Contains, StartsWith, or EndsWith query in Entity Framework when you know the pattern you'd like to find. But how to do the equivalent of "LIKE [Column]"?
For instance, this is easy:
Name LIKE '%Th'
But how do you do this? where Prefix is a column.
Name LIKE [Prefix]
I tried to use the SqlMethods and got the following error.
LINQ to Entities does not recognize the method 'Boolean Like(System.String, System.String)' method, and this method cannot be translated into a store expression.
I resolved this problem by using LINQ to Entities to bring back the set of data that I wanted, then using LINQ to Objects to filter the data.
I do not think there is currently a way to have a LINQ to Entities query be resolved in a database server as ...
... LIKE [column-name]
First, SqlMethods is for use in LINQ-to-SQL, not LINQ-to-Entities.
The best you can do to use the filter in the database engine (so you don't have to pull all data in memory first) is:
context.Entities.SqlQuery("SELECT * FROM EntityTable WHERE Name LIKE Prefix")
I am thinking of designing a business rule engine which basically generates an EF query from a set of string values stored in a database.
For e.g. I will store the connection string, table name, the where condition predicate, and select predicate as string fields in a db and would like to construct the EF query dynamically. For e.g.
var db = new DbContext(“connectionstring”);
var wherePredicate = Expression.FromString(“p => p.StartDate > new DateTime(2014,5,1))
var selectPredicate = Expression.FromString(“p => p”)
var results = db.Set(“Projects”).Where(wherepredicate).Select(selectPredicate)
For constructing the predicates I can use DynamicExpression or Dynamic LINQ library.
However how do I access db.Set(“Projects”) where Projects is the entity name and apply the where and select predicates? (or something like db[“Projects”].Where().Select).
I tried the non-generic version of the DbContext.Set(Type entityttype) method, however couldn’t figure out how to apply Where and Select predicates to the returned object.
I am trying to avoid generating SQL queries and instead rely on dynamically generated EF code.
This doesn't make much sense. You can create method that will work on string instead of generic type using reflection, but you'd have to return DbSet not DBSet<T>. And on that one you cannot execute LINQ's methods (basically), because there's no type (during compilation). Of course you can do it all the way using reflection, but then, why??? You're loosing 90% of what O/R mapper does for you.
None of the many questions on this topic seem to match my situation. I have a large data model. In certain cases, only a few of the fields need be displayed on the UI, so for those I replaced the LINQ to Entity query that pulls in everything with an Entity SQL query retrieving only the columns needed, using a Type constructor so that I got an entity returned and not a DbDataRecord, like this:
SELECT VALUE MyModelNameSpace.INCIDENT(incident.FieldA, incident.FieldB, ...) FROM ... AS ...
This works and displays the fields in the UI. And if I make a change, the change makes it back to the entity model when I tab out of the UI element. But when I do a SaveChanges, the changes do not get persisted to the database. No errors show up in the Log. Now if I very carefully replace the above query with an Entity Sql query that retrieves the entire entity, like this:
SELECT VALUE incident FROM MyDB.INCIDENTs AS incident...
Changes do get persisted in the database! So as a test, I created another query like the first that named every column in the entity, which should be the exact equivalent of the second Entity SQL query. Yet it did not persist changes to the database either.
I've tried setting the MergeOption on the returned result to PreserveChanges, to start tracking, like this:
incidents.MergeOption = MergeOption.PreserveChanges;
But that has no effect. But really, if retrieving the entire entity with Entity Sql persists changes, what logical purpose would there be for behaving differently when a subset of the fields are retrieved? I'm wondering if this is a bug?
Gert was correct, the problem was that the entity was not attached. Dank U wel, Gert! Ik was ervan verbluft!
I just wanted to add a little detail to show the full solution. Basically, the ObjectContext has an Attach method, so you'd think that would be it. However, when your Entity SQL select statement names columns, and you create the object using a Type as I did, the EntityKey is not created, and ObjectContext.Attach fails. After trying and failing to insert the EntityKey I created myself, I stumbled across ObjectSet.Attach, added in Entity Framework 4. Instead of failing, it creates the EntityKey if it is missing. Nice touch.
The code was (this can probably be done in fewer steps, but I know this works):
var QueryString = "SELECT VALUE RunTimeUIDesigner.INCIDENT (incident.INCIDENT_NBR,incident.LOCATION,etc"
ObjectQuery<INCIDENT> incidents = orbcadDB.CreateQuery<INCIDENT>(QueryString);
incidents.MergeOption = MergeOption.PreserveChanges;
List<INCIDENT> retrievedIncidents = incidents.ToList<INCIDENT>();
orbcadDB.INCIDENTs.Attach(retrievedIncidents[0]);
iNCIDENTsViewSource.Source = retrievedIncidents;
I have the code below (this is actually part of a much more complicated query, but I have isolated the issue to this particular line to help with debugging) which per everything I have read should create an IN clause in SQL, assuming I am using EF4. As far as I can tell, I am using EF4 (We are using .NET Framework 4 for our projects and when I look at the System.Data and System.Data.Entity they both say version 4.0.0.0 for all the projects)
int[] assessmentIDs; // this is just here to show what this is,
// but it is a params parameter passed to this methed
var assessments = from cert in container.ProctorAssessmentCertifications
where assessmentIDs.Contains(cert.AssessmentID)
select cert.ID;
However, when I run this, I get the runtime error:
LINQ to Entities does not recognize the method 'Boolean Contains[Int32](Int32[], Int32)' method, and this method cannot be translated into a store expression.
When I use LinqPad, it does correctly output an IN clause like one would expect in EF4.
My questions are:
A. What am I doing wrong and how do I make this work?
B. How do I force EF4 to be called if in fact it's not? I can find no reference in any web.config file that point it to the older version.
Contains does not get translated into valid SQL because assessmentIDs is not IQueryable, it is an in-memory object. So you'll have to pull the data out first, and then do the check.
var assessments = (from cert in container.ProctorAssessmentCertifications
select cert.ID).ToList() //no longer IQueryable.
var result = assessments.Intersect(assessmentIDs);