Query conceptual model with Entity SQL - c#

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>.

Related

TableName (Contains / Regex) When Creating An Entity - Entity Framework - Table Prefix

I'm trying to create an EF model based on an existing MySQL Database.
Upon creating an entity, I map it using:
[Table("databaseName.tableName")] or :
modelBuilder.Entity<Lang>().ToTable("tableName") in OnModelCreating.
The issue I have is that the table names could have an unexpected prefix.
What I want to do is, without knowing the prefix, search for any table in the database that:
(Something like)EndsWith("tableName") use it, or:
which name matches a Regex.
Is this doable? The alternative would be to ask the user for the TablePrefix specific to his/her database and work with it (modelBuilder.Entity<Lang>().ToTable(prefix + "tableName") but that would be quite inconvenient. Since the prefix is the only thing that can change from database to an other, it would be really helpful to be able to detect tables by their name.
You can't query the database in OnModelCreating, but you can use the Connection String to open an ADO.NET Connection to the database and run a query to retrieve the table names and construct a mapping between the Entity types and the table names.

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) *

Retrieving records from table where a column may have multiple rows of data

I have a database with several tables and I am using the following query to return a record that matches a string(Name).
In the MHP table there is a Name field(primary key), Num_Sites and a few more, but these are the only ones I am concerned with.
In the MHP_Parcel_Info table there are many fields with one of them being Name(foreign key). There is a parcel_id field and in some case there may only be one parcel for one name, but there may also be many parcels for a Name.
As it is now my query will return one of the rows for instances where there are multiple parcels for a name.
What I would like to do is: if there is more than one parcel for a Name, have all the parcels put into a list(so I can display in listbox on form).
My SQL skills are limited and I don’t know how I would go about doing something like this.
SELECT MHP_Parcel_Info.*, MHP.NUM_SITES FROM MHP_Parcel_Info INNER JOIN MHP ON " +
"(MHP_Parcel_Info.MHP_NAME = MHP.MHP_NAME) WHERE MHP_Parcel_Info.MHP_NAME='" + strValue + "'"
This is not something you can do directly in SQL. There's no way to select data in a parent/child structure in a SQL query - you have to do that as a post-processing step.
Since this is tagged as C# and Winforms I'm assuming this is from inside a .Net app. You will need to execute the query as you have it above, then in C# you can use the LINQ GroupBy extension method on the result to group the results into a list of IGrouping objects which use the name as the key, and has all of the parcel info as the items in the list.
Even better, if you are using (or can use) LINQ to SQL or Entity Framework you can just write a linq query that fetches the data from the database and does the grouping all at once.

LINQ to SQL query has wrong values in results

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...

Categories

Resources