Quantcast
Channel: West Wind Message Board Messages
Viewing all articles
Browse latest Browse all 10393

Re: Saving changes with EfCodeFirst business wrapper?

$
0
0
Re: Saving changes with EfCodeFirst business wrapper?
West Wind Web Toolkit for ASP.NET
Re: Saving changes with EfCodeFirst business wrapper?
Dec. 15, 2012
09:01 am
3O20JC6Z1Show this entire thread in new window
Gratar Image based on email address
From:Matt Slay
To:Rick Strahl
For one thing it's really bad practice to pick up a quote object as a parameter and then post it to the database.

From your helpful posts in recent days, I get the "view model" pattern that you (and plenty of others) advocate. Of course, I've heard about this paradigm for years, but until I actually experienced some obstavles in my own code, it has seemed more of an academic idea, rather than something that I might actually benefit from in a real-word app.

Apparently, if are showing every field from the table in the view (or using hidden fields for the ones that you were not showing) you can get by with some qucky dirty demo apps by using the data entity as the view model, but you are saying that no professionally architected app should do this, right?

What a shame that the very latest MVC 4 Web Project template that Visual Studio uses, as well as 99% of the demos and blog samples that you see, use a blatant example of the naughty "data entity as the view model" pattern to get you started.

.

EF doesn't work if you just 'assign' an entity. Entities have to be created through EF or be attached in some way. IOW, you can't just use the quote object and assign it to Entity and expect that to work.

Using the bus object you can use quoteBO.Attach(quote). With plain EF the dbSet has a similar function with options for setting the change state (which the BO method does automatically).

This should work.

HOWEVER! This is not the right way to do this.

For one thing it's really bad practice to pick up a quote object as a parameter and then post it to the database. What if some robot decides to send you a quote object with a valid id and only one value filled? At that point your entity would actually write out a single property and a bunch of empty property effectively overwriting the entire record in the database. It also means that if you have POST data on a View that every field has to be there! If it's not those missing fields effectively get wiped out.

A better way is to read the values from the quote and assign them - either manually or using something like AutoMapper or WebUtils.FormVarsToObject(). These tools have options to avoid writing missing values into the object. This should ensure that only values that are actually passed are updated, and not the entire entity.

This is something that bugs me around model binding: Rather than being able to update an existing object the object has to be a parameter and get instantiated. While ModelBinding actually does the right thing (reads only POST values), that effect is unfortunately lost when you do it on a newly created instant.

That aside though - Attach() should work.

+++ Rick ---



Rick - I have a basic MVC4 CRUD app up and running, but I cannot figure out how to call the Save() method from the post-back of the Edit action on my controller.

If I understand this EF stuff properly, somehow, I've got to get the Quote entity back into the EfCodeFirst Context, and mark it as "modified" so it will be saved back to the database. I just cannot figure out the right sequence. I've tried to "attach" the Quote entity but that fails for some reason, and when I try calling .Save(quote), it does not give an error, but yet the changes do not get saved.

Here's what I've tried:

[HttpPost]public ActionResult Edit(Quote quote) {try {if (ModelState.IsValid) { var quoteBO = new busQuote();//quoteBO.Attach(quote);//quoteBO.Context.Entry(quote).State = System.Data.EntityState.Modified; quoteBO.Entity = quote; quoteBO.Save(quote);return RedirectToAction("Index"); } return RedirectToAction("Index"); }catch {return View(); } }

The Quote entity is a complex entity, as it has a related Customer object, and a child collection of line items:

Quote entity has:
- various properties from its own table field
- has a Customer object (per PK/FK relationship defined in model attributes)
- has a collection of QuoteItems which are line items on the Quote.

Eventually, I will need to save changes to the QuoteItems collection as well, but for now, I'm just wanting to accomplish saving basic properties on the top Entity in the busQuote object (i.e. the to the Quote table).

Here's the busQuote class:

publicclass busQuote : EfCodeFirstBusinessBase<Quote, QuoteContext> { .... }

Here's the Context:

publicpartialclass QuoteContext: EfCodeFirstContext {public DbSet<Quote> Quotes { get; set; } public DbSet<QquoteItem> QuoteItems { get; set; }public DbSet<Customer> Customers { get; set; }protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new quoteMap()); modelBuilder.Configurations.Add(new quoteitemMap()); modelBuilder.Configurations.Add(new customerMap()); } }




Viewing all articles
Browse latest Browse all 10393

Trending Articles