I´m wondering if its possible to work with one object in Entity Framework and when I update the principal, EF creates or updates the lists, Let me show one example:
Objects Relation (image: http://i.stack.imgur.com/GJ2FW.png)
In this example, we have a Companie with a list of Employees with has a list of addresses and phones. If a create one Company, in disconnected mode. After that I will add some Employees with Addressees and Phones, It´s possible, like NHibernate, send this back to Context and the EF resolve what is update and what is created?
Like this?
using (var db = new CompanyContext())
{
db.Companies.Attach(cia);
db.Entry(cia).State = EntityState.Modified;
db.SaveChanges();
}
Thanks in advance.
In contrast to NHibernate, EF must be told what to update/create/delete explicitly in disconnected mode, as far as know. The good news is that there's a solution:
http://blog.brentmckendrick.com/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates-of-a-graph-of-detached-entities/
I used it in one of my projects, worked a treat for me.
Related
I'm creating a web app based on a database. The datas in the database need to be displayed, edited and deleted by the web app user.
Right now I need to remove elements in my sqlite database table after the user inputs the name of the database table and the id (which is also the primary key) of the element. How can I do it?
I always used Entity Framework before and also in the Web App so I was looking for a solution with it, but if there's a simpler way to do it, I'll stick with it.
Thank you
I think the answer here is similar but I need help to adapt it to what I need now.
Entity Framework C# queries from strings
this is the UI
and here is the endpoint in the backend
//DELETE method
[HttpDelete("DeleteElementInTable")]
public IActionResult DeleteElementInTable(string tableName, string elementKey) //url query parameters
{
var db = new MyContext();
//code to remove the item ... something like:
DbManager.RemoveElement(tableName, elementKey); //DbManager is the static class dealing with the db context
return //csv of the deleted element;
}
I'm still a young developer but here I can see there are some lacks of knowledge. First of all, which technology are you using to build your web-app? From what you posted my guess is you are trying to use MVC. As #Panagiotis Kanavos said above you need an entity to interact with the database if you want to use Entity Framework, through which you don't need to pass table name in your GET function. Last but not less important you can't execute the delete operation in a GET function.
I apologise if this has been asked already, I am struggling greatly with the terminology of what I am trying to find out about as it conflicts with functionality in Entity Framework.
What I am trying to do:
I would like to create an application that on setup gives the user to use 1 database as a "trial"/"startup" database, i.e. non-production database. This would allow a user to trial the application but would not have backups etc. in no way would this be a "production" database. This could be SQLite for example.
When the user is then ready, they could then click "convert to production" (or similar), and give it the target of the new database machine/database. This would be considered the "production" environment. This could be something like MySQL, SQLServer or.. whatever else EF connects to these days..
The question:
Does EF support this type of migration/data transfer live? Would it need another app where you could configure the EF source and EF destination for it to then run through the process of conversion/seeding/population of the data source to another data source?
Why I have asked here:
I have tried to search for things around this topic, but transferring/migration brings up subjects totally non-related, so any help would be much appreciated.
From what you describe I don't think there is anything out of the box to support that. You can map a DbContext to either database, then it would be a matter of fetching and detaching entities from the evaluation DbContext and attaching them to the production one.
For a relatively simple schema / object graph this would be fairly straight-forward to implement.
ICollection<Customer> customers = new List<Customer>();
using(var context = new AppDbContext(evalConnectionString))
{
customers = context.Customers.AsNoTracking().ToList();
}
using(var context = new AppDbContext(productionConnectionString))
{ // Assuming an empty database...
context.Customers.AddRange(customers);
}
Though for more complex models this could take some work, especially when dealing with things like existing lookups/references. Where you want to move objects that might share the same reference to another object you would need to query the destination DbContext for existing relatives and substitute them before saving the "parent" entity.
ICollection<Order> orders = new List<Order>();
using(var context = new AppDbContext(evalConnectionString))
{
orders = context.Orders
.Include(x => x.Customer)
.AsNoTracking()
.ToList();
}
using(var context = new AppDbContext(productionConnectionString))
{
var customerIds = orders.Select(x => x.Customer.CustomerId)
.Distinct().ToList();
var existingCustomers = context.Customers
.Where(x => customerIds.Contains(x.CustomerId))
.ToList();
foreach(var order in orders)
{ // Assuming all customers were loaded
var existingCustomer = existingCustomers.SingleOrDefault(x => x.CustomerId == order.Customer.CustomerId);
if(existingCustomer != null)
order.Customer = existingCustomer;
else
existingCustomers.Add(order.Customer);
context.Orders.Add(order);
}
}
This is a very simple example to outline how to handle scenarios where you may be inserting data with references that may, or may not exist in the target DbContext. If we are copying across Orders and want to deal with their respective Customers we first need to check if any tracked customer reference exists and use that reference to avoid a duplicate row being inserted or throwing an exception.
Normally loading the orders and related references from one DbContext should ensure that multiple orders referencing the same Customer entity will all share the same entity reference. However, to use detached entities that we can associate with the new DbContext via AsNoTracking(), detached references to the same record will not be the same reference so we need to treat these with care.
For example where there are 2 orders for the same customer:
var ordersA = context.Orders.Include(x => x.Customer).ToList();
Assert.AreSame(orders[0].Customer, orders[1].Customer); // Passes
var ordersB = context.Orders.Include(x => x.Customer).AsNoTracking().ToList();
Assert.AreSame(orders[0].Customer, orders[1].Customer); // Fails
Even though in the 2nd example both are for the same customer. Each will have a Customer reference with the same ID, but 2 different references because the DbContext is not tracking the references used. One of the several "gotchas" with detached entities and efforts to boost performance etc. Using tracked references isn't ideal since those entities will still think they are associated with another DbContext. We can detach them, but that means diving through the object graph and detaching all references. (Do-able, but messy compared to just loading them detached)
Where it can also get complicated is when possibly migrating data in batches (disposing of a DbContext regularly to avoid performance pitfalls for larger data volumes) or synchronizing data over time. It is generally advisable to first check the destination DbContext for matching records and use those to avoid duplicate data being inserted. (or throwing exceptions)
So simple data models this is fairly straight forward. For more complex ones where there is more data to bring across and more relationships between that data, it's more complicated. For those systems I'd probably look at generating a database-to-database migration such as creating INSERT statements for the desired target DB from the data in the source database. There it is just a matter of inserting the data in relational order to comply with the data constraints. (Either using a tool or rolling your own script generation)
I have read over several other questions about this, but I haven't been able to get it to work for me.
I'm using EF Code First, I have two entities Room and Equipment with a many-to-many relationship. It's correct in the DB with an intermediate table that contains a foreign key to both the Room and Equipment tables. However, I haven't been able to get an insert to work.
var room = roomService.FindById(roomId);
var equipment = service.FindById(equipmentId);
//do I need to do both of these?
room.Equipment.Add(equipment);
equipment.Rooms.Add(room);
db.SaveChanges();
This doesn't work at all. I have also trying using Attach to attach both the relevant entities to the context based on advice in other questions but it just seems to stop the code from running. Also, I tried manually change the EntityState to Modified and that didn't help either.
Any ideas?
I am having trouble understanding at a fundamental level how a one to many relationship should be managed in Entity Framework. In my application I have two tables, DISPLAY_MASTER, and DISPLAY_ITEMS. Their relationship is like so:
DISPLAY_MASTER.DISPLAY_ID 1----->* DISPLAY_ITEMS.DISPLAY_ID
Entity Framework organizes this really intuitively. I am left with a strongly typed DISPLAY_MASTER object that has an ICollection property called DISPLAY_ITEMS.
My confusion lies within how to save the DISPLAY_ITEMS collection back to the database. In my application I am reading in all of the DISPLAY_ITEMS for the particular DISPLAY_MASTER using LINQ into a List<DISPLAY_ITEMS> object called _displayItems. This is then bound to a DataGrid for editing using MVVM. The user can edit existing DISPLAY_ITEMS, delete existing DISPLAY_ITEMS, or add new DISPLAY_ITEMS using the DataGrid. My binding works perfectly and these changes are reflected in _displayItems. Once it comes time to save is where I stop feeling confident in my code. When the user clicks save I am setting the DISPLAY_MASTER's ICollection like so:
_displayMaster.DISPLAY_ITEMS = _displayItems;
Is this the proper way to be working on an Entity Framework collection? Or should I be binding the DataGrid directly to the _displayMaster.DISPLAY_ITEMS object? Or some other method? The reason I am not confident is because if I try to validate the _displayMaster.DISPLAY_ITEMS entity using:
DbEntityValidationResult validationResults = _context.Entry(_displayMaster.DISPLAY_ITEMS).GetValidationResult();
I get an error saying 'List1' is not part of the collection, which obviously doesn't seem right.
Any advice or guidance would be appreciated.
Thanks.
It depends.
If you disconnect the entities from their database context when you bind them to the grid (i.e. if you dispose the context after loading the entities and create a new context when it comes to save the changes) then it's not so easy. You will have to load the master including the old items from the database, merge the changes into that collection based on your new edited collection from the grid and then save the changes. An example how to do that is here.
If you keep the entities attached to the context you have loaded them into while the user is editing it's much easier if you just directly bind _displayMaster.DISPLAY_ITEMS to the grid because EF is then able to track all the changes you are performing on the collection and update the object graph automatically to the database when you call SaveChanges.
Since you tagged the question with WPF you might have the second option (depending on your application's architecture). In web applications for example the second option doesn't exist at all because all editing happens in a browser which is disconnected of course from the context.
This may be a bit silly, but all the applications I've built have always utilized the EF Code-First approach to generate the database. When using this method, I've always accessed the database through the Context:
public class RandomController : Controller
{
public CombosContext db = new CombosContext();
//
// GET: /Home/
public ActionResult Index()
{
var rows = db.Combos.OrderBy(a => a.Id).ToList();
However, what if the database is already created for me, OR I create one by adding entities to the schema/design surface and then generate the database from that. How would I access the db without the
public CombosContext db = new ComboxContext();
If the DB is already created, you can use the Database First approuch: http://blogs.msdn.com/b/adonet/archive/2011/09/28/ef-4-2-model-amp-database-first-walkthrough.aspx
A basic setup would by to rightclick the project in the solution explorer and click Add > new item. On the dialog, select Data on the left pane and ADO.net Entity Data Model and follow the wizard to create your model based on the database. This way, you will have a context object exactly the way you have with code first (with some minor changes, but works almost the same).
You can still do this with Code first and is the better approach IMHO. Use the Entity Framework Power Tools to reverse engineer your existing database into a code-first model.
http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d/
See my demo on using it at:
http://channel9.msdn.com/Events/TechEd/NorthAmerica/2012/DEV215