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

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,

Related

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();

Entity Framework 6 mapping a custom SQL query to an Entity

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

EF 4.1 code first - How to update/delete many to many join table entries automatically

I have 2 entities, let's say, Trip and Activity. The relationship between them is many to many so a join table is created automatically by EF.
Entity Trip attributes:
-Id (PK) Generated by database
-Name
-Description
-Property1
-Property2
-Property3
Entity Activity attributes (this entity contains fixed records -read only-, no records are inserted here on performing inserts):
-Id (PK) Generated by database
-Name
-Description
-Cost
Join table contains 2 columns, that is, the IDs of the above entities, that are primary and foreign keys at the same time.
I have no problems inserting entries which automatically EF creates join table TripActivities and add entries successfully to it. Also entries are added successfully to entity Trip and it leaves unchanged entity Activity.
My problem is on updating entries, for example, - suppose user can modify information related to a trip from the GUI - so I take all the info from this GUI and I perform the following steps to update the existing trip:
Trip trip = Context.Trips.Find(id); // Search for the appropriate trip to update from Id
trip.Name = ObtainNameFromGUI();
trip.Description = ObtainDescriptionFromGUI();
trip.Property1 = ObtainProperty1FromGUI();
trip.Property2 = ObtainProperty2FromGUI();
trip.Property3 = ObtainProperty3FromGUI();
trip.Activities = new List<Activity>();
// From the GUI user selects from a checkbox list the activities associated to the trip
// So we read its Ids and from those ids we fetch from database the activities to obtain
// the info related to each activity selected in the GUI. This is all done inside the
// below method.
List<Activity> activities = this.ObtainActivitiesSelectedFromGUI();
// If no activites selected (=null) I want EF automatically deletes the entries in the
// joined table for this trip. And of course, if there are activities selected, EF
// should update the respectives entries in the joined table for this trip with the new
// ones.
if (activites != null)
{
activities.ForEach(a =>
{
trip.Activities.Add(a);
});
}
context.Trips.Add(trip);
context.SaveChanges();<br><br>
By doing this I want EF updates all the entities related (except Activity as it has fixed entries, must be kept unchanged), that is, Trip and the joined table automatically but it does not work: a new trip is created and more entries in the joined table (The only thing that is working is that entity Activity is kept unchanged as I want).
How to achieve this? I have spent a lot of hours trying to do this but without success...
Thanks in advance.
EDIT:
I have removed line:
context.Trips.Add(trip);
Now the results are:
-Entity Trip is correctly updated, no new records added which is Ok.
-Entity Activity is kept unchanged which is Ok.
-Join table: The old records for current trip being updated are not updated, instead new records are inserted for the current trip which is not correct.
I have used a different approach for similar scenario that I faced, which works well with Detached Entities. What I ended up was finding out which entities were added and which ones deleted by comparing GUI(detached entity) values to the database values. Here is the sample code that I have used. The entities in play are RelayConfig and StandardContact which have many to many relationship
public void Update(RelayConfig relayConfig, List<StandardContact> exposedContacts) {
RelayConfig dbRelayConfig = context.RelayConfigs.Include(r => r.StandardContacts)
.Where(r => r.Id == relayConfig.Id).SingleOrDefault();
context.Entry<RelayConfig> (dbRelayConfig).CurrentValues.SetValues(relayConfig);
List<StandardContact> addedExposedContacts =
exposedContacts.Where(c1 => !dbRelayConfig.StandardContacts.Any(c2 => c1.Id == c2.Id)).ToList();
List<StandardContact> deletedExposedContacts =
dbRelayConfig.StandardContacts.Where(c1 => !exposedContacts.Any(c2 => c2.Id == c1.Id)).ToList();
StandardContact dbExposedContact = null;
addedExposedContacts.ForEach(exposedContact => {
dbExposedContact = context.StandardContacts.SingleOrDefault(sc => sc.Id == exposedContact.Id);
dbRelayConfig.StandardContacts.Add(dbExposedContact);
});
deletedExposedContacts.ForEach(exposedContact => { dbRelayConfig.StandardContacts.Remove(exposedContact);});
You will use something like this. Assuming that you will get the related objects from the UI and just you are going to update the same in the database, some thing like the following will work.
context.Products.Attach(product);
context.ObjectStateManager.ChangeObjectState(product, System.Data.EntityState.Modified);
context.ObjectStateManager.ChangeObjectState(product.ProductDescription, System.Data.EntityState.Modified);
context.ObjectStateManager.ChangeObjectState(product.ProductModel, System.Data.EntityState.Modified);
context.SaveChanges();
As you may see here, we are setting the EntityState as Modified which hints EF to perform update for the related tables too.
Please post back your queries or any issues that you may encounter in this implementation.

New column issue after association

I created 2 tables in Visual studio say TA and TB. In edmx file I made 1-to-many association between TA and TB. After making association, a new column is generated in TB named TAId.
I just want to know whether I have to add that column in the TB table in database?
EDIT : Exception I got:
nCeremony.msl(23,10) : error 3004: Problem in mapping fragments starting at
line 23: No mapping specified for properties CourseOption.MenuId in Set
CourseOptions.
An Entity with Key (PK) will not round-trip when:
Entity is type [CeremonyDBModel.CourseOption]
Ceremony.msl(31,10) :
error 3004: Problem in mapping fragments starting at line 31:No mapping
specified for properties Menu.CeremonyId in Set Menus.
An Entity with Key (PK)
will not round-trip when:
Entity is type [CeremonyDBModel.Menu]
A one-to-many association is done by having records in a child table reference their parent.
Consider an example of customers and purchases. A customer may make many purchases, but each purchase can only belong to one customer. Consider the following two tables:
customers purchases
============ ===========
id name id customer_id product
Each customer has a unique ID and a name. Each purchase also has a unique ID and a product name. However, in order to have a one-to-many association, the purchases table must also reference which customer made the purchase. You couldn't do this in reverse, or you would have duplicate names of customers each referencing some purchase.
For example:
customers purchases
============ ===========
id name id customer_id product
--- -------- --- ------------ --------
1 John 1 1 apple
2 Mary 2 1 orange
3 2 banana
In this example you can see that John purchased an apple and a orange, and Mary purchased a Banana.
The customer_id column is necessary for the purchases table to establish the relationship with the customers table.
By creating the association between your TA and TB tables, Visual Studio has created the column TAid for you, because that is how relational databases like MS SQL Server handle them.

Entity Framework select single value from row

I am using Entity Framework from .NET 3.5
I have two tables with 0-1 to many relation. Let's say Citizen and City. Each citizen has foreign key column (ID) that connects him to City.
When i select single citizen, i also need to select the name of the city where he lives.
Because city table contains tons of data that is not really related to citizen, so i don't want to retrieve it from database to save some bandwidth.
Currently i am using Include() function, but it grabs all the data from the City related to citizen, while i need only name.
Is there a way to write a query to select single cell from the whole row in EF and without creating new classes or interfaces or repositories?
Here is my Include:
Citizen citizen = db.Citizens.Include("Cities").First(p => p.citizen_id == id);
You do this by projecting, e.g.
var c = from c in db.Citizens
where c.citizen_id == id
select new
{
Name = c.Name,
CityName = c.City.Name
};
You can also project onto POCOs.
You cannot tell the EF to retrieve an object of type Citizen with a related City but with only City.Name filled in. The EF will not partially materialize an entity. Use view / presentation models or DTOs instead of entities when you need only a few fields.

Categories