Question

I'm very new to MVC so pardon my unfamiliarity with it.

I'm experimenting with a project and I've run in to the following problem: How to bring in data from a separate database table if it's not connected through a foreign key relationship.

I have a table where one of the columns may or may not match a value in another table, and if it does I need to mark it.

Example:

Lets say for simplicity there's a table Wishlist and a table StuffAtStore and they have these fields:

StuffAtStore
  Price
  Name

Wishlist
  Name
  Person

I want to list all the items in the StuffAtStore and if any are such that StuffAtStore.Name == Wishlist.Name I want to add the text " On " + Wishlist.Person + "'s wishlist" after the price.

Based on some suggestions I found online what I could get to work was creating something like this

public partial class StuffAtStore
{
    public string PersonIfAny 
    {
        get
        {
            FooEntities db = new FooEntities();

            if (db.Wishlist.Any(w => w.Name == Name))
            {
                return db.Wishlist.First(w => w.Name == Name).Person;
            }
            else
            {
                return "";
            }
        }
    }
}

And

@Html.DisplayFor(modelItem => item.Price)

@if (item.PersonIfAny != "")
{
    @Html.PersonIfAny(modelItem => item.PersonIfAny) 
}

But naturally this is very very slow.

What's the best/ most proper way to do this with MVC?

Was it helpful?

Solution 2

You should really consider having a ViewModel class such as follows:

class StuffViewModel {
    string Name { get; set; }
    string Price { get; set; }
    string PersonIfAny { get; set; }
}

Then, in your Controller/Action,:

void YourAction(...) {
    FooEntities db = new FooEntities();
    var stuff = db.StuffAtStore.Select(s => 
        new StuffViewModel
        {
            Name = s.Name,
            Price = s.Price,

            // This will use Outer Apply, which may not be available
            // for EF providers other than Microsoft's MSSQL provider.
            PersonIfAny = db.Wishlist.Where(w => w.Name == s.Name)
                            .Select(w => w.Person).FirstOrDefault();
        }

    foreach(var s : stuff) 
    {
        s.PersonIfAny = s.PersonIfAny ?? "";
    }


    return View(stuff);

}

OTHER TIPS

This really isn't an MVC question but more a question of how to retrieve the data in an efficient manner.

It looks like you're using Entity Framework. Even though there's no database-level foreign key between StuffAtStore and Wishlist you can still create a relationship between those two entities in EF. Then, when retrieving StuffAtStore you could simply include Wishlist. If the Wishlist doesn't contain the item the collection will be empty.

Having said that, if your wishlist items are really store items you should probably go all the way back to your database design and have a foreign key between those tables rather than trying to connect them via an arbitrary name column.

Maybe you could make a ViewModel for your view. Actually, it's a simple class you give to your view from your controller and inside your declare some members (a List<string> for instance, that will contain your already prepared strings to display) and a constructor that will make the query with the join between your tables (well, a left join in fact).

I think that ViewModels (not as in the MVVM pattern, but almost) are the best way to present complex structures of data to your view, making it really simpler if your base classes (your Model) dont suit perfectly.

Here are some good tutorials : http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-3

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top