MVC3 ViewModel with multiple LINQ queries, is it making multiple DB calls? - asp.net-mvc-3

If I am creating a viewmodel to pass to a view and my viewmodel is comprised of several
properties from the same object, how should I create the LINQ query? At the moment I'm doing it like this:
TaskEditViewModel viewModel = new TaskEditViewModel
{
Task = taskRepository.Tasks.FirstOrDefault(t => t.Id == id),
Status = (taskRepository.Tasks.FirstOrDefault(t => t.Id == id).CompletionDate.ToString() == "") ? "close" : "open",
Account = taskRepository.Tasks.FirstOrDefault(t => t.Id == id).Accounts.First()
};
return View(viewModel);
My taskRepository returns IQueryable, so does this mean I am making 3 seperate db calls? Should I be making one call and then building the viewmodel from the results?

I decided to revisit this on its anniversary. I think this would have been making multiple db calls due to lazy loading, so not very efficient.
As Ingo Vals correctly commented, the CompletionDate and Account properties are included in my Task model, so I should have just done something like this:
Task viewModel = taskRepository.Tasks.FirstOrDefault(t => t.Id == id)
return View(viewModel);
Then in my view I can get the CompletionDate and Account properties from the view model

Related

Manually loading navigation properties in MVC 6

What is the best way to manually load navigation property in MVC 6?
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(Reservation reservation, bool ignoreConflicts = false)
{
int id = reservation.ItemID; // correct item ID
Item item = reservation.Item; // null
}
In this example, when user submits a form, I get a Reservation object with all navigation properties set to null.
The best way I can think of is manually looking up the Item DbSet to find the item with matching ID and assigning it to the navigation property.
Well, first thing first... you are in an MVC action. What you will receive will be from the client. Not the database directly.
So reservation.Item might not be null but it might not be the real data either.
In this scenario, you first have to retrieve your data from the server and then do one of two things:
Update the EF7 entity directly by hand from what you received from the client
Use TryUpdateModelAsync to update your current entity automatically.
It could be as simple as:
public ActionResult Update(Reservation reservation)
{
var item = context.Items.FirstOrDefault(x => x.ID == reservation.ItemID);
await TryUpdateModelAsync(item);
// todo: save context
// return....
}
This is an Entity Framework 7 issue, not an MVC6 one.
Lazy loading isn't implemented for EF7 yet, possibly it won't be at all.
You can track the ticket here https://github.com/aspnet/EntityFramework/issues/3797
This means instead we need to do it as you suggested; something like:
Item item = context.Items.FirstOrDefault(x => x.ID == reservation.ItemID);

How to show custom query result to view mvc3 Razor

I have Custom query Result as
public ActionResult Index()
{
var Query = (from E in db.SITE_MASTER.AsEnumerable()
where E.IS_PAGE == true
select new
{
E.POST_TITLE,
E.POST_TEXT
}).ToList();
return View(Query);
}
Now,
How can I make view for this result or How can I create View for this Result Query.
Thanks...
You can pass an anonymous type as a model, but please don't. It's ugly and will lead to maintenance problems.
As an alternative either use the ViewBag or create concrete type and pass that.

MVC 3 / EF 4.2 - Editing against ViewModel, do I save against Model or ViewModel?

My first MVC3 EF 4.2 site and I'm confused on some things, currently on ViewModels when querying and saving. Please correct me if I explain this poorly, i'm not sure how to term this. The .edmx automatically created the table classes but I read it was better to create a ViewModel, considering I need to join tables to display/edit my Product completely. The controller code below is where I join tables to output a Product to edit, and then save. My question - what is the right way to save the Product, to the Product.cs model generated by DbContext or my own ProductViewModel.cs?
Is there an easier method to query a product and join the tables and then map to the viewmodels parameters, or do I keep doing all this in the controller like below?
I also want to save/update the product each time someone views/clicks on the product, so I wasn't sure if I create a separate ViewModel for updating just that parameter or again, use the Product model.
Hope that makes sense! I can explain further if needed.
private SiteForgeEntities db = new SiteForgeEntities();
public ActionResult Edit(int id)
{
var viewModel = (
from a in db.Products
join b in db.Sites
on a.SiteId equals b.SiteId
join c in db.Sections
on a.SectionId equals c.SectionId
join d in db.Affiliates
on a.AffiliateId equals d.AffiliateId
select new ProductViewModel()
{
ProductId = a.ProductId,
Product = a.Product,
Description = a.Description,
Image = a.Image,
Price = a.Price,
Clicks = a.Clicks,
Link = a.Link,
Site = b.Site,
Section = c.Section,
Affiliate = d.Affiliate
}).Single(x => x.ProductId == id);
return View(viewModel);
}
[HttpPost]
public ActionResult Edit(Product product)
{
...update database...do I pass in and save back to Product or my ProductViewModel
}
You use ViewModel to pass multiple models to the view, but when you save data, you need to save it to the appropriate model. If you are adding or modifying products, you will add items to products (using your DbContext). If you have one-to-many relationship defined between two models (in your Product.cs model you might have a property declared as:
public virtual ICollection<SomeOtherModel> SomeOtherData { get; set; }
you can use this to build a table instead of passing everything in a ViewModel. There is a nice tutorial here regarding the CRUD operations using EF4. Have a look at these short tutorials that can give you an idea about your strategy http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc.

Add values to object in LINQ to SQL expression

I have this contact list which I'm building using LINQ to SQL. The query to get a list of contacts is:
return db.Contacts.ToList();
In the list I also want to display each contact's primary e-mail address. To do this I first rewrite my query:
return (from db.Contacts
select c).ToList();
I found this nice way to do left joins:
return (from db.Contacts
from ce in ContactEmails.Where(x => x.ContactID == c.ContactID && c.IsPrimary).DefaultIfEmpty()
select c).ToList();
But now I want to add this PrimaryEmailAddress to my Contact object. To do this I have added a property (PrimaryEmailAddress) to the generated Contact class, using a partial class.
Is it possible in the LINQ query to add the value to c.PrimaryEmailAddress somehow? My solution right now is to create anonymous objects and then iterate them.
Here's one way to do it:
In your entity designer, create an association between your Contact class and your ContactEmail class (just guessing at your class names here). Here are some instructions on creating an association.
Then, configure your DataContext to load only your primary ContactEmail. Here are some instructions on filtering child data at the DataContext level.
And here is an entirely different way to do it:
In your partial Contact class, in your partial OnLoaded() method, query the primary ContactEmail. For example:
partial void OnLoaded()
{
// get your DataContext here
this.PrimaryContactEmail = db.ContactEmails
.Where(ce => ce.ContactID == this.ContactID && ce.IsPrimary)
.SingleOrDefault();
}

How do you re-use select statements with Entity Framework?

Given the following query:
var query = from item in context.Users // Users if of type TblUser
select new User() // User is the domain class model
{
ID = item.Username,
Username = item.Username
};
How can I re-use the select part of the statement in other queries? I.e.
var query = from item in context.Jobs // Jobs if of type TblJob
select new Job() // Job is the domain class model
{
ID = item.JobId,
User = ReuseAboveSelectStatement(item.User);
};
I tried just using a mapper method:
public User MapUser(TblUser item)
{
return item == null ? null : new User()
{
ID = item.UserId,
Username = item.Username
};
}
With:
var query = from item in context.Users // Users if of type TblUser
select MapUser(item);
But if I do this, then the framework throws an error such as:
LINQ to Entities does not recognize
the method 'MapUser(TblUser)' method,
and this method cannot be translated
into a store expression.
You can't use regular function calls in a query definition like that. LINQ needs expression trees, it can't analyze compiled functions and magically translate that to SQL. Read this for a more elaborate explanation
The techniques used in the cited article are incorporated in linqkit (factoring out predicates) and might be of help, though I'm not sure you can use the same technique for managing projections, which is what you seem to want.
The more fundamental question you should ask yourself here IMHO is whether you really need this extra mapping layer? It seems like you're implementing something that EF is already perfectly capable of doing for you...
Try making your MapUser method static.

Resources