LINQ to SQL query has wrong values in results - c#

I have a LINQ query that has the incorrect results, but when I profile the SQL generated, the SQL results are correct.
ApplicationsEntities context = new ApplicationsEntities();
var query = from documentation in context.Documnetations
where documentation.Application_Version_ID == app_ver_id
orderby documentation.Name
select documentation;
docs = query.ToList<Documnetation>();
I get back two duplicates : "How to install Office 2003" and "How to install office 2003"
Below is the output of the profiled SQL:
What could be happening to the assignment of the results from the generated SQL?

Update based on comments
Your linq query is fine, but in your model you have to set the Primary Key/Entity Key
Linq-to-Sql
In your dbml, you need to change your primary key from Application_Version_ID to Documentation_Id
Linq-to-Entities
In your model, you need to change your entity key from Application_Version_ID to Documentation_Id

This happens when the structure of one or more tables have changed.
Delete your tables and regenerate them in your EDM. (Entity Data Model)
Right click, Update Model from Database..., Add...

Related

How to select data from entity framework without selecting its icollection(foreign table)

I am using C# to select data from my database. Now i have two table, the first one is aspnetuser, the second one is aspnetuserroles, the aspnetuserroles have the foreign key linkage with aspnetuser table, when i perform the following query
db.AspNetUsers.ToList()
the aspnetroles data will appeared in the aspnetusers data. This will cause my datatable unable to display its data because datatable expect one value in one column parameter. If the aspnet roles data inside that json, it will appear as multiple row and datatable dont accept it.. If i remove that foreign key linkage, my datatable will display without any error.
In this case, what i want is, how to select aspnetusers table without pulling out its foreign table. For eg
db.AspNetUsers.Select(x=>x.AspNetUsers).ToList();
Turn off the LazyLoading. So that the children will not be fetched automatically.
try doing something like this (good for keeping the return object light and leave behind any unwanted columns):
(I have just made up some col name, but you get the idea.)
var result = (from a in db.AspNetUsers
select new AspNetUser { Name = a.Name,
othercol1 = a.othercol1,
othercol2 = a.othercol2,
}).ToList();
Footnote: In reality it is generally not good practice to return the actual db Entity to the front end so you might want to have your own Data Transfer Objects (DTO).
You configured that in the mappings using the Fluent API's methods
HasOptional
HasMany
Ignore
etc. But normally, I create schema-bound views in database and then map that in EF. It works really well in cases when we're only interested in a flattened query without all the joints.
Or use Linq to EF projections as JonhB's answer...
var result = (from a in db.AspNetUsers
select new AspNetUser { Name = a.Name,
...
}).ToList();
Just make sure you don't call ToList on db.AspNetUsers because that would materialize the query on AspNetUsers and all it's foreign key references and as result the projection is done in-memory after the query returns

Entity Framework SQL query string to get history data from temporal tables throwing a data-table incompatible error

I had same problem explained in this question.
Found a great answer by Matt in the same post which helped me a lot. It works for insert and update queries. I'm using IDbCommandTreeInterceptor and Ignored ValidFrom and ValidTo columns.
Now I'm trying to query some history data. As Entity Framework Linq queries cant get data from temporal tables, I'm forced to used SQL query string.
var result = this.Context.VehicleSets.SqlQuery("SELECT Id, Name FROM T.VehicleSet FOR SYSTEM_TIME ALL WHERE Id = 1").ToList();
This line throws an error in run-time.
The data reader is incompatible with the specified 'Model.VehicleSet'. A member of the type, 'ValidFrom', does not have a corresponding column in the data reader with the same name.
Matt in his answer has set clause for insert and update commands.
I tried using DbQueryCommandTree to set same clause for querying, but DbQueryCommandTree doesn't have SetClauses command.
Any help will be very much appreciated.
In the SQL "Select" query, you need to include all the fields that you have in the VehicleSets class... appart from "Id" and "Name" fields, you need to have at least a Start and End dates (that hold the temporal data...).
* (I know it's a late reply, but it may help others) *

The schema returned by the new query differs from the base query (C#/SQL - VS 2012)

For a homework task I have to develop a C# application to interface with a SQL Server database file (.mdf), providing a dataGridView to browse the contents, and several buttons to execute queries.
I have been going well, found how to add queries to my table adapter, how to call them etc.
Now I am having problems making a query that returns the maximum pay in hourlyPayRate.
I have a database employee that contains the following attributes: employeeID, name, position, hourlyPayRate.
My query is
SELECT MAX(hourlyPayRate)
FROM employee
I right click employeeTableAdapter, click "Add Query...", name it Max and put in the query. When I click okay I get the following error message:
The schema returned by the new query differs from the base query.
The query executes correctly in the query builder, it is only when I click "OK" to save it that I receive the error.
Looking around SE there are no definitive answers to this question.
Thanks, Michael.
The solution has been found, for all those wondering.
The problem is that the query returns a table which has a different number of columns that the database.
Usually in most DBMS's this is not an issue, but for some reason Visual Studio was having none of that.
The solution was this query:
SELECT employeeID, name, position, hourlyPayRate
FROM employee
WHERE (hourlyPayRate =
(SELECT MAX(hourlyPayRate) AS MaxRate
FROM employee AS TempTable))
And then trimming the unneeded from the result as you like. For me this was as simple as having a label that derived it's data only from the hourlyPayRate attribute.
The actual reason for this is that the base QUERY returns more or less columns than the QUERY you are adding . Visual Studio cares about this ; and should not after all it is a new query.
NOTE: We are talking query columns not Database Table Columns. The Error regards Base Query - for example a fill, and perhaps you want to have a fill by and hide the field of a foreignID - because your base query outputs that column, and your added query does not - the new query differs from the base in that the columns are not the same. (I think this is done to ensure bound objects are properly bound; but I really do not know (think datagridview.)
So for example
Fill() Query
SELECT Id, Name, FKtblThing_ID
FROM ITEMS
Adding this query works..
FillByID() Query
SELECT Id, Name, FKtblThing_ID
FROM ITEMS
WHERE (FKtblThing_ID = #FKtbl_ThingID)
If instead you tried this - it would not work.
FillByID() Query
SELECT Id, Name
FROM ITEMS
WHERE (FKtblThing_ID = #FKtbl_ThingID)
This is the error you would receive:
The schema returned by the new query differs from the base query.
Everyone is wrong here, you don't edit the sql in the table adapter but edit the sql in the dataset.

Will linq bring back all records from a stored procedure call, and then filter?

Given the EF linq below, will all the records in the stored proc usp_GetTestRecords() come across and then get filtered?
TestRecordsDBEntities dataContext = new TestRecordsDBEntities();
var tests = dataContext.usp_GetTestRecords();
var filtered = tests.Where(x => x.GroupId == groupId)
.OrderByDescending(y => y.Name)
.ToList();
Yes all data will be first fetched in the memory and then filtered on the client side. Using stored procedure with EF is not a good idea. You will loose the advantage of lazy,eager or explicit loading here. However if you let EF generate queries for you then it will be compiled will all filters and executed on server
As an alternative, you may want to consider creating a table value function rather than stored proc. The advantage here is that result-set of the function can be joined with other tables on the server side. The disadvantage is that you are limited in terms of what you can do inside of the function and the database does not have access to indexes for the function results that you could with indexed views.
See more about using TVS with EF at http://blogs.msdn.com/b/efdesign/archive/2011/01/21/table-valued-function-support.aspx
Sprocs will allways return all the records affected by te query associated to it. If you want to add a where clause just add a param to your sproc and perform the filtering in sql. Check this for more information How to pass Parameters to Stored Procedure from Entity Framework?

Query conceptual model with Entity SQL

My application is based on Entity Framework. I am offering users to query a particular table by saving their queries in another table. For example, TopQuery table in database stores all the queries which are popular among users.
These queries are performed on table "TableData"
For test purposed, I have tried the following and it works. The only problem is that it returns all columns where as I would like to use columns that are mentioned by users in their queries.
string queryString =
#"SELECT VALUE table FROM TestEntities.TableData AS table where table.col1 = 'test'";
ObjectQuery<TableData> productQuery2 =
new ObjectQuery<TableData>(queryString, context);
My problem is that if user stores a query in database like this, it doesn't work.
SELECT table.col1, table.col2, table.col3 FROM TestEntities.TableData AS table where table.col1 = "test"
I get the exception: The specified cast from a materialized System.Data.Objects.MaterializedDataRecord' to'TestEntities.TableData'type is not valid.
I have also tried this without any luck.
"SELECT it.col1, it.col2 FROM TableData WHERE it.col1 = 'test'"
What should I do in such case?
Regards,
You will never get ObjectQuery<TableData> once you try to select only subset of columns. Using ObjectQuery<TableData> works only when you select whole entity as your first query did - that is a strongly typed approach enforced by Entity framework.
ESQL doesn't support projection in the way Linq-to-entities does (by allowing you to project to a new anonymous or non mapped type). When using projection with ESQL you must work with ObjectQuery<DbDataRecord>.

Categories

Resources