I am using a view to return a complex search query. When I usin linq to query against EF it is returning the same row 3 times(the actual rowcount is correct).
using LinqPad I have run the same linq against my ef entity and the actual database view.
ReadmitPatientList
.AsQueryable()
.Where("PatientLastName.StartsWith(\"cooper\")")
.OrderBy (rpl => rpl.PatientLastName)
.Dump();
That is the linq I am using for both.
linqpad shows the lambda as this:
EF:
ReadmitPatientList.MergeAs (AppendOnly)
.Where ( => .PatientLastName.StartsWith ("cooper"))
.OrderBy (rpl => rpl.PatientLastName)
DB
ReadmitPatientList
.Where ( => .PatientLastName.StartsWith ("cooper"))
.OrderBy (rpl => rpl.PatientLastName)
I cannot post the results...but EF returns three rows of the same record. DB returns 3 rows of individual records. As does my sql query.
What about my EF LINQ do I need to change to make it work correctly?
The sql code that is generated by the EF Linq query Actually returns the correct results if run in SQL explorer.
This happens if Patient entity doesn't have primary key or columns inferred as primary key are same across multiple records in the result set. EF uses internally identity map which requires that each uniquely identified record must reuse the same instance of the entity. So if you return three records from the database which have same unique identification for EF will return enumeration of three same instances representing the first record from the result set (more about identity map also here). The same behaviour is in Linq-to-sql's DataContext.
Related
I have a Reporting Services Project on SQL Server 2008 R2. The point is to provide users with a data model they can use as a data source for Report Builder 3. So I have created my data source views as usual and then the Report model with no problems.
For example in my model I have a table Student which has a relationship with table Course using a CourseSK key (one to one). So I am using student.CourseSK = course.CourseSK to return to the query designer only the course.Coursename field under the Student entity (I have hidden everything else from the course table.)
The problem is that when I test it in ReportBuilder, using the query designer when I add field CourseName from entity student in the dataset, it returns two fields instead of one: CourseName and Course where course returns some values like AAAAAEAA =. I guess is some object reference but can be very confusing to the end user. How can I make this disappear?
Indeed it turns out to be a unique entity identifier used for aggregating fields with non unique values. It cannot be removed from the data set. More information here Answer
Setup:
ASP .NET Core 1 Web API
MySQL Server Community Edition 5.7
Entity Framework Core 1.0.1 with Pomelo MySQL driver (3 separate contexts, 3 separate databases).
Contexts: MainContext (maindb), Module1Context (module1db), Module2Context (module2db).
I want to execute a query that returns a list of Posts (from Module1Context), but I need to filter them by author rights (from MainContext, User entity).
So, what I am trying to do is execute a query with a JOIN clause to a different database table:
var results = await module1Ctx.Posts.FromSql("select * from `module1db`.`posts` as `p` inner join `maindb`.`users` as `u` on `p`.`AuthorId`=`u`.`Id` where <conditions here>").ToListAsync();
When this executes, I get a SQL Exception telling me that "Sequence contains more than one element". If I select p.*, it will work, but I also need to pull the user data.
The Post entity contains a reference to the user ID (public long AuthorId {get;set;}), and a fake navigation property, NotMapped, as EF couldn't join 2 databases automatically.
My first question is - would this be possible. I have a strong feeling that this will work, but that I am missing something small.
If this doesn't work, I will resort to manually executing the query, using the DbContext's Connection. If I will do this, how can I map the results into a list of Posts, including the User data?
Sequence contains more than one element
This tells you that a column appears more than once. For example if you have "ModifiedDate" column in both tables, when you do select * it will appear twice in the result set (once p.ModifiedDate and once in u.ModifiedDate.
Also additional to this, the columns returned must exactly match the model. No property which is defined in the model must be missing, that's why p.* will work.
But unless your Post model does define fields which represent values from User table, you can't return them, because it must exactly match Post and it's mapped properties.
Ad-hoc support (mapping result to an arbitrary model, like a view model) is not yet implemented in EntityFramework Core 1.0 and is a feature on the roadmap for future versions.
From the EntityFramework Core Roadmap:
Critical O/RM features
...
Raw SQL queries for non-Model types allows a raw SQL query to be used to populate types that are not part of the model (typically for denormalized view-model data).
Edit
Also from the EFCore documentation
Limitations
There are a couple of limitations to be aware of when using raw SQL queries:
SQL queries can only be used to return entity types that are part of your model. There is an enhancement on our backlog to enable returning ad-hoc types from raw SQL queries.
The SQL query must return data for all properties of the entity type.
The column names in the result set must match the column names that properties are mapped to. Note this is different from EF6.x where property/column mapping was ignored for raw SQL queries and result set column names had to match the property names.
The SQL query cannot contain related data. However, in many cases you can compose on top of the query using the Include operator to return related data (see Including related data).
I have a regular view in sql server 2008 and I`m using entity framework generate design from database approach. I already know about the keys issues for views in entity framework but that is not my solution. When I query select * from view, it brings out 3 rows which is right, but all the rows are the same and are the first row in the database view.
some help would be very appreciated.
I already know about the keys issues for views in entity framework but that is not my solution. When I query select * from view, it brings out 3 rows which is right, but all the rows are the same and are the first row in the database view.
What you describe is exactly the problem caused by incorrect key. Your three rows must have unique identification - some column or set of columns must uniquely identify each possible returned record. These columns must be set as entity key in the designer.
You can also avoid this issue by not using change tracking when loading data from the view because returned entities are read-only. You have to use MergeOption.NoTracking for that ObjectSet:
context.MyViewEntities.MergeOption = MergeOption.NoTracking;
var data = context.MyViewEntities.ToList();
I have one specific view created in my DB(joins about 5-6 tables with a left join).This view is added to my edmx (entity framework 1.0) . Recently I noticed that one of the column records obtained using the edmx (linq to entities and then ToList()) got duplicated multiple times though in the database view they were different
Column-N (Expected result/ result from DB view)
---------
data1
data2
data3
data4
data5
Column-N(Actual result generated by entity framework)
---------
data1
data1
data1
data1
data1
I fired up my SQL profiler,got the query which was sent by my application to the SQL Server, ran it and it returned me the expected result.
MSDN has a similar post here and here but the moderator has not elaborated on how to solve this problem. My key happens to be a GUID
The root cause you pointed out I think
is correct, the problem is on the
application side EF mapping, as EF has
different object mapping rules with
database. when the query results have
been returned from database, the EF
will do the mapping on application
memory according to its own designed
logic.
It's important to take these logic
into account when you desingn your
view query in your database side. I
think you should do some adjustment on
your view query.
I am not sure whether you have sorted
the problem, if not please provide the
database structure related to this
issue and the view query you have
written.
Thanks Binze
Has someone encountered a similar problem before ?
The problem is in fact with the key. You have to a) have a unique identifier for each row in the view. and b) map that key accordingly in the edmx. Otherwise as your quote states, the mapping logic will see each subsequent row and figure that it can use the same object instance that it returned before
Same problem for me.
An Entity View (VReport) was generated automatically from VS2010 wizard to something like:
class VReport
Line: int (key)
Desc: string
Date: DateTime
When I retrieved the records from the database, the SQL query was formed correctly and returned the expected (and distinct) results, but the Entity Framework instead returned a lot of duplicated records.
But instead, also the Date column/field would have to partecipate in the formation the Entity KEY
So, to resolve this issue, I changed the property of the field from Entity Key: false -> true
class VReport
Line: int (key)
Desc: string
Date: DateTime (key)
I've been using the ADO.NET Strogly-Typed DataSet model for about 2 years now for handling CRUD and stored procedure executions. This past year I built my first MVC app and I really enjoyed the ease and flexibility of LINQ. Perhaps the biggest selling point for me was that with LINQ I didn't have to create "Insert" stored procedures that would return the SCOPE_IDENTITY anymore (The auto-generated insert statements in the DataSet model were not capable of this without modification).
Currently, I'm using LINQ with ASP.NET 3.5 WebForms. My inserts are looking like this:
ProductsDataContext dc = new ProductsDataContext();
product p = new product
{
Title = "New Product",
Price = 59.99,
Archived = false
};
dc.products.InsertOnSubmit(p);
dc.SubmitChanges();
int productId = p.Id;
So, this product example is pretty basic, right, and in the future, I'll probably be adding more fields to the database such as "InStock", "Quantity", etc... The way I understand it, I will need to add those fields to the database table and then delete and re-add the tables to the LINQ to SQL Class design view in order to refresh the DataContext. Does that sound right?
The problem is that any new fields that are non-null are NOT caught by the ASP.NET build processes. For example, if I added a non-null field of "Quantity" to the database, the code above would still build. In the DataSet model, the stored procedure method would accept a certain amount of parameters and would warn me that my Insert would fail if I didn't include a quantity value. The same goes for LINQ stored procedure methods, however, to my knowledge, LINQ doesn't offer a way to auto generate the insert statements and that means I'm back to where I started.
The bottom line is if I used insert statements like the one above and I add a non-null field to my database, it would break my app in about 10-20 places and there would be no way for me to detect it. Is my only option to do a solution-side search for the keyword "products.InsertOnSubmit" and make sure the new field is getting assigned?
Is there a better way?
Thanks!
Create a NON-Null field, with a default value of whatever. This way the old rows will have a default value you know of, letting you go back and add values to the table.