Entity Framework 6 mapping a custom SQL query to an Entity - c#

I am very new to ASP.NET MVC and Entity Framework at the moment. I've been working with it for about 3 months at the current moment in time.
I have an ASP.NET MVC 5 application that's running Entity Framework 6. This is a code first approach from an existing database with auto migrations enabled so all of my Entity classes are auto generated. I am trying to add a view to my MVC application that returns a specific result set. Currently the previous developer has the application set up to only accept an Entity class to display data to a DataTable DataTables.net. To clarify further:
I have two Entity tables in my model that are tables in MySQL.
| Samples | SampleLocation |
|:------------------|---------------:|
| Id | LocationId |
| DateAssigned | Name |
| CheckedInDate | Size |
| SampleLocationId | |
| ...etc | ...etc |
What I'm trying to accomplish is querying both tables and returning the results to my MVC application in a view. From there run an Update and update a couple of columns in the Samples table. Below is the roughly the query that returns the results I need.
SELECT Samples.Id, samples.CheckedInDate, SampleLocation.Name, SampleLocation.Size,
SampleLocation.LocationId
FROM (Samples join SampleLocation
ON ((Samples.SampleLocationId = SampleLocation.LocationId)))
WHERE isnull(samples.CheckedInDate) ORDER BY samples.Id
From the research that I have done there are a few ways to accomplish this. The ways that I've tried that would give me a class I could use are creating a stored procedure and then updating the model - this breaks the model and unmaps every single entity in the model. I have tried creating a view with the query to add to the model - but this breaks it as well and unmaps everything. I later found out that this is a bug.
So my question is, how can I map a query to an Entity that return results to a view? Is there a better way to go about this?

There are several ways to accomplish what you want to do, using either Entity Framework only or extra tools like Dapper
Entity Framework Only:
First you can use Linq to extract the data, I'll look something like this:
var list = from s in Samples
join l in SampleLocations
on s.Id equals l.LocationId
where s.CheckedInDate == null
select new
{
s.Id,
s.CheckedInDate,
l.Name,
l.Size,
l.LocationId
};
Dapper:
The second method is using dapper, the only real difference here is that you would be working with your queries directly, so instead of linq you had something like this:
Connection.Query(#"SELECT Samples.Id, samples.CheckedInDate,
SampleLocation.Name, SampleLocation.Size,
SampleLocation.LocationId
FROM Samples
join SampleLocation
ON Samples.SampleLocationId = SampleLocation.LocationId
WHERE isnull(samples.CheckedInDate) ORDER BY samples.Id");
For both:
In your update method, you first have to retrieve the entities, for that you can use the DbSet.Find method or another query, after that you call DbConext.SaveChanges.

This is the solution to my problem. Basically manually creating an Entity within the XML and mapping it to a virtual table.Entity Framework DefiningQuery

Related

How to update multiple tables using one query in Entity Framework?

I want to update three table with one Query in Entity Framework:
Customer_Identification Region Customer Account
| Id |Region_Id |Customer Id
| Name |Region_Name |Bank_Name
| Address |Bank Account
| Region_Id
I created a class Customer with all fields required and I used a join query to select what information I want to update in database.
I try to update changes in this way :
dataContext.Entry( Customer).State = System.Data.Entity.EntityState.Modified;
dataContext.SaveChanges();
I get this error:
The entity type DbQuery`1 is not part of the model for the current context.
How is possible to update database without using multiple queries?
Best regards,

Map stored procedure with multiple resultset returned in EF Core

I am currently migrating an already established website from old ASP.NET to ASP.NET Core 2.2. The database is a shared database across other platforms and is also established therefore I cannot just changed anything from it.
I came across to this problem when I had to call a stored procedure from EF Core where this stored procedure returns 3 result sets. The result set of the stored procedure is like this.
Table 1
ColumnName1 | ColumnName2 | SomeColumn | AndMoreColumns
------------+-------------+------------+---------------
Value1 | value 2 | value 3 | Value 4
Table 1
Column1 | Column2
-----------+----------
value1 | value 2
Table 3
Column1
-------
Value1
Table 1 and table 2 are related to each other. This table will always return 1 row on table 1 and table 2 can return multiple rows while table 3 is static.
Now, my question is. How do I map this result set to an EF Core Query<T> model builder? I want to map it per column name since I want to make the column names more friendly. An example that I had that did not work is like this.
modelBuilder.Query<MyModel>(a =>
{
a.Property(b=>b.ModelId).HasColumnName("ColumnName1");
a.Property(b=>b.ModelName).HasColumnName("ColumnName2");
...
});
but unfortunately, the above mapping did not work. Especially for the 2nd table.
First at all, the result from stored procedure is not a table, I mean an user table.
So, I think there are two possible solutions for your question:
Work with pure ADO.NET, execute data reader and cast the result to result models
Use an external approach from EF Core
For point 1, please read this question: EF Core query stored procedure map to types
For point 2, please read this question: Working with multiple resultset in .net core
Also you can read this issue: Support multiple resultsets #8127
Let me know if this answer is useful.
You might want this post until EF Core implement similar function:
https://www.danylkoweb.com/Blog/aspnet-core-with-entity-framework-core-returning-multiple-resultsets-OL

Asp.net/SQL - Retrieving data from multiple tables using foreign keys

I'm new to ASP.NET and SQL, and I'm trying to build a Web Forms project that will basically display data using grids.
I'm using Entity Framework along with a Data Transfer Object and a Data Access Layer for displaying/editing data.
My issue is that I'm not sure what is the best way of retrieving data using foreign keys.
Example:
Table 1 - Products
|(PK) Product ID | Product Name | Country ID(FK)
Table 2 - Countries
|(PK) Country ID | Country Name|
Final Result Should be:
Product ID | Product Name | Country Name|
What's the best way to accomplish that?
Thanks in advance
The best approach is use a projection to do that.
Your code will be similar to the code below:
context.Products.Select(x=>new ProductDto
{
ProductId=x.ProductId,
ProductName=x.Name,
CountryName=x.Country.Name
});
Using projections you will ensure that is retrieving only the necessary data from DB.
Hope this helps!
You can make LINQ query from this one. Better, you create one separate class and retrieve only data which you want.
SQL Query :
SELECT P.ProductID, P.ProductName, C.COuntryName FROM Products P
INNER JOIN ON Countries C ON C.CountryID = P.CountryID
Execute Query using EF :
context.Database.SqlQuery<ProductDTO>(query).ToList();

SQLite code-first onModelCahnge how to keep the old data from databse

i'm new to Sqlite and EF.
i created a DbContext with some model classes which will create a local database on app start. Database will get updated while application running.
When i change something in model (ex: add new property to a class) and run the application, the whole database is recreating from scratch. so i'm loosing my saved data.
How can i keep the old data even though the model changes.
For Ex:
Database.table1
ID | Name
1 | abc
2 | xyz
when i add new prop to table1 class, its recreating table with empty data, where i need something like this if possible.
Database.table1
ID | Name | NewProp
1 | abc | Null
2 | xyz | Null
The database initializer is what causes the database to be recreated on a model change. So you can disable the initializer by setting it to null:
Database.SetInitializer<MyContext>(null);
This of course means you will need to manually make your database match the model. Another option is to use an initializer that doesn't drop and create the database. Looks like there is a project here for SqlLite: https://github.com/msallin/SQLiteCodeFirst So then you could use SqliteCreateDatabaseIfNotExists.
Finally, you could use migrations. Doesn't look like that's supported out of the box so you would need a third party tool for that. Entity Framework MigrationSqlGenerator for SQLite

Combining multiple rows into one entity in Entity Framework 4.1

I've been trying to grow my EF understanding from just querying tables to creating Entities that match my business objects so I can code against my business objects rather than my data objects. I read articles that suggest this is possible, but all of their examples are rather trivial and involve just combining two tables. My situation is a little more complicated and I'm not sure how to proceed.
I have two tables (simplified below)
CREATE TABLE [dbo].[BarEvents]
(
[BarGUID] UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID(),
[Bar] INT NULL
)
CREATE TABLE [dbo].[BarLog]
(
[BarGUID] UNIQUEIDENTIFIER NOT NULL,
[BarLogGUID] UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID(),
[BarEventTime] DATETIME NOT NULL DEFAULT GETUTCDATE()
)
So if I join these tables, for a specific BarGUID, so if I had 1 Bar and 4 bar events logged, I'd have 4 rows, but what I want is just the most recent BarEventTime. So I would like to join and have just one row:
I can do this trivially in EF:
var query = barEntities.BarEvents.Where( q=> q.BarGUID = '0000-0000-0000-0000')
.Select(barEvent =>
new LogItem()
{
Bar = barEvent.Bar,
BarEventTime = barEvent.BarLog.Max(u => u.BarEventTime)
});
But from what I've read, I should be able to define a LogItem entity, and place this logic somehow in my LogItem entity, then write queries against that. My problem is I only see trivial join conditions when I'm trying to join my tables in the entity definitions. Is there a way to do this? Or a guide?
Any help would be appreciated.
Thank you.
Why don't you do the following:
Create a SQL View in the Database that does what you want
Add the view to your EF Context
Use the newly created entity that is based on the view

Categories