MVC 3, code-first, and sample data - asp.net-mvc-3

I'm using code-first, and am trying to generate some sample data, but am stuck.
var ts = new List<VehicleType>
{ new VehicleType { TypeName = "Car" },
new VehicleType { TypeName = "Truck" },
new VehicleType { TypeName = "Van" },
new VehicleType { TypeName = "SUV" },
new VehicleType { TypeName = "RV" }
};
var mr = new List<Manufacturer>{
new Manufacturer { ManufacturerName = "Ford" },
new Manufacturer { ManufacturerName = "Dodge" },
new Manufacturer { ManufacturerName = "Hyundai" },
new Manufacturer { ManufacturerName = "Mazda" },
new Manufacturer { ManufacturerName = "Honda" },
new Manufacturer { ManufacturerName = "Lexus" },
new Manufacturer { ManufacturerName = "Cadillac" },
new Manufacturer { ManufacturerName = "Jayco" }
};
var vm = new List<VehicleModel>{
new VehicleModel { ModelName = "Focus" },
new VehicleModel { ModelName = "Elantra" },
new VehicleModel { ModelName = "3" },
new VehicleModel { ModelName = "4X4" },
new VehicleModel { ModelName = "CRX" },
new VehicleModel { ModelName = "Element" },
new VehicleModel { ModelName = "SE 541" },
new VehicleModel { ModelName = "LE 4X" }
};
new List<Inventory>
{
new Inventory {VehicleModel = vm.Single(g => g.ModelName == "Focus"), Manufacturer = mr.Single(g => g.ManufacturerName == "Ford"), VehicleType = ts.Single(g => g.TypeName == "Car"), Price = 10999, Mileage = 241092, Year = 2001, Description = "Includes all G37x AWD Sport standard equipment FORD", Colour = "Tan", CarImageUrl = "/Content/Images/car1.jpg", DateReceived = "01/06/2011"},
}.ForEach(a => context.Inventorys.Add(a));
This works fine. My Inventory table in populated with the data from the other tables (VehicleType, Manufacturer, and VehicleModel). Here are their models:
public class Manufacturer
{
[Key]
public int ManufacturerId { get; set; }
public string ManufacturerName { get; set; }
}
public class VehicleModel
{
[Key]
public int ModelID { get; set; }
public string ModelName { get; set; }
}
public class VehicleType
{
[Key]
public int TypeId { get; set; }
public string TypeName { get; set; }
}
Now lets say the Manufacturer model had another attribute besides ManufacturerName, let's say it also has ManufacturerLocation. When I try to add that attribute into the Inventory list:
new List<Inventory>
{
new Inventory {VehicleModel = vm.Single(g => g.ModelName == "Focus"), Manufacturer = mr.Single(g => g.SomeAttributeFromManufacturerTable)
All attributes from the Manufacturer table will appear, but after I use one of those attributes, there doesn't seem to be an opportunity to enter in the rest of the attributes. Is this because it expects me to enter in the ManufacturerId attribute, and it will automatically associate the rest on the attributes through its primary key? I hope I'm making sense, I find this hard to explain.

Related

Setting the default value of multiple dropdown lists on page load

I have a model,
public class Customer
{
public string Name { get; set;}
public string CountryCode { get; set;}
}
In the controller
var model = new List<Customer>
{
new Customer { Name = "foo", CountryCode = "US"},
new Customer { Name = "bar", CountryCode = "UK",
};
return PartialView("_Edit", model);
An extension method for displaying all countries:-
public class CountryList
{
public static IEnumerable<SelectListItem> CountrySelectList
{
get
{
var list = new List<SelectListItem>()
{
new SelectListItem { Value = "US", Text="US" },
new SelectListItem { Value = "UK", Text="UK" },
};
return list;
}
}
}
In the PartialView
#model List<Customer>
#Html.DropDownListFor(model => model[i].CountryCode, CountryList.CountrySelectList, "Select Country Type")
But the drop down doesn't select each customer's country code? Any thoughts?
PS: It is using model[i] => which is of type Customer, for simplicity i had removed the forloop before rendering the html tags.
#using(Html.BeginForm())
{
for(int i = 0; i < Model.Count(); i++)
{
#Html.TextBoxFor(model => model[i].Name)
#Html.DropDownListFor..........
}
}
Because your CoutryList helper does returns a list of SelectListItems that all have Selected property set to False (which is default).
I would rewrite your helper method as follows:
public static IEnumerable<SelectListItem> CountrySelectList(string selectedCountryCode)
{
get
{
var list = new List<SelectListItem>()
{
new SelectListItem { Value = "US", Text="US" },
new SelectListItem { Value = "UK", Text="UK" },
};
var selectedListItem = list.FirstOrDefault(t=>t.Value== selectedCountryCode);
if(selectedListItem!=null)
selectedListItem.Selected=true;
return list;
}
}
In view:
#Html.DropDownListFor(model => model[i].Customer, CountryList.CountrySelectList(model[i].Customer.CountryCode), "Select Country Type")

Guidance on Seeding Data Entity Framework

I'm having problems with seeding some constant data when dropcreatedatabase is initiated. I have looked over some similar questions but I'm having difficulties understanding why my code isn't working.
All help is greatly appreciated (c:
Here is my SampleData Model with Seed Data
public class SampleData : DropCreateDatabaseIfModelChanges<fotmEntities>
{
protected override void Seed(fotmEntities context)
{
var genres = new List<Genre>
{
new Genre { Name = "Specials" },
new Genre { Name = "Online" },
new Genre { Name = "Services" },
new Genre { Name = "Food" },
new Genre { Name = "Misc" },
new Genre { Name = "Auto" }
};var localities = new List<Locality>
{
new Locality { Name = "Location1" },
new Locality { Name = "Location2" },
new Locality { Name = "Location3" },
new Locality { Name = "Location4" },
};
new List<Discount>
{
new Discount { Title = "Title A", Genre = genres.SingleOrDefault(g => g.Name == "Specials"), Information = "8.99M", Locality = localities.Single(a => a.Name == "Location1"), DiscountArtUrl = "/Content/img/placeholder.gif" },
new Discount { Title = "Title B", Genre = genres.SingleOrDefault(g => g.Name == "Specials"), Information = "8.99M", Locality = localities.Single(a => a.Name == "Location2"), DiscountArtUrl = "/Content/img/placeholder.gif" },
new Discount { Title = "Title C", Genre = genres.SingleOrDefault(g => g.Name == "Services"), Information = "8.99M", Locality = localities.Single(a => a.Name == "Location3"), DiscountArtUrl = "/Content/img/placeholder.gif" },
new Discount { Title = "Title D", Genre = genres.SingleOrDefault(g => g.Name == "Food"), Information = "8.99M", Locality = localities.Single(a => a.Name == "Location4"), DiscountArtUrl = "/Content/img/placeholder.gif" },
new Discount { Title = "Title E", Genre = genres.SingleOrDefault(g => g.Name == "Misc"), Information = "8.99M", Locality = localities.Single(a => a.Name == "Location1"), DiscountArtUrl = "/Content/img/placeholder.gif" },
new Discount { Title = "Title F", Genre = genres.SingleOrDefault(g => g.Name == "Auto"), Information = "8.99M", Locality = localities.Single(a => a.Name == "Location2"), DiscountArtUrl = "/Content/img/placeholder.gif" },
}.ForEach(a => context.Discounts.Add(a));
Here is my context model:
using System.Data.Entity;
public class fotmEntities : DbContext
{
public DbSet<Discount> Discounts { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Locality> Localities { get; set; }
}
and my Global.asx
protected void Application_Start()
{
System.Data.Entity.Database.SetInitializer(
new fotm.Models.SampleData());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}

MVC complex data query

I have a query as below :
`Table
London flat
London flat
London House
Paris flat
Paris flat
Paris House
Paris House`
I am looking to turn this to below object in linq. Anyone please help me.
public class BrowseModel
{
public string TownName { get; set; }
public int FlatCount { get; set; }
public int HouseCount { get; set; }
}
The result need to be like:
London 2Flat 1 house
Paris 2Flat 2 houses
Hi if i haven't understood your question wrong you can try it like this
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
//Ignore above code
List<Table> list = new List<Table>();
//Suppose this what you db returns
list.Add(new Table() { TownName = "London", HouseType = HouseType.Flat });
list.Add(new Table() { TownName = "London", HouseType = HouseType.Flat });
list.Add(new Table() { TownName = "London", HouseType = HouseType.House });
list.Add(new Table() { TownName = "Paris", HouseType = HouseType.Flat });
list.Add(new Table() { TownName = "Paris", HouseType = HouseType.Flat });
list.Add(new Table() { TownName = "Paris", HouseType = HouseType.House });
list.Add(new Table() { TownName = "Paris", HouseType = HouseType.House });
var result = list.GroupBy(o => o.TownName).Select(s => new BrowseModel() { TownName = s.First().TownName, FlatCount = s.Where(f => f.HouseType == HouseType.Flat).Count(), HouseCount = s.Where(h => h.HouseType == HouseType.House).Count() }).ToList();
}
}
public class BrowseModel
{
public string TownName { get; set; }
public int FlatCount { get; set; }
public int HouseCount { get; set; }
}
public class Table
{
public string TownName { get; set; }
public HouseType HouseType { get; set; }
}
public enum HouseType
{
House=0,
Flat=1
}
I hope this will give you idea.

How can I select data from multiple tables?

In my MVC project, I have some tables like this:
Form (FormID, SectionID)
Section (SectionID, SectionName)
SectionQuestion (SectionID, QuestionID)
Question (QuestionID, Content)
A form has multiple sections, and a section has some questions.
I can get all question for the FormID. But I want to get a list of sections (which contain questions) for the model.
It means in the view I want to do something like this:
#Model IEnumerable<MedialForm.Models.Sections>
foreach (var section in Model)
{
//Show questions
}
Can you guys help me? :)
You will not see a list of sections for a form, since the Form can only have 1 section. (i.e. the SectionID is defined in Form, and not FormID in Section). However the following Linq query will return the section and the associated questions for a specified FormID:
void Main()
{
var sections =
new []
{
new Section { SectionID = 1, SectionName = "SectionName1" },
new Section { SectionID = 2, SectionName = "SectionName2" }
};
var forms =
new []
{
new Form { FormID = 1, SectionID = 1 },
new Form { FormID = 2, SectionID = 1 },
new Form { FormID = 3, SectionID = 2 },
new Form { FormID = 4, SectionID = 2 }
};
var questions =
new[]
{
new Question { QuestionID = 1, Content = "Question1" },
new Question { QuestionID = 2, Content = "Question2" }
};
var sectionQuestions =
new[]
{
new SectionQuestion { SectionID = 1, QuestionID = 1 },
new SectionQuestion { SectionID = 2, QuestionID = 1 },
new SectionQuestion { SectionID = 2, QuestionID = 2 }
};
var formId = 4;
var result = forms
.Join(
sections,
f => f.SectionID,
s => s.SectionID,
(f, s) => new { Form = f, Section = s })
.Join(
sectionQuestions,
jfs => jfs.Section.SectionID,
sq => sq.SectionID,
(jfs, sq) => new { Form = jfs.Form, Section = jfs.Section, sq.QuestionID })
.Join(
questions,
jfsq => jfsq.QuestionID,
q => q.QuestionID,
(jfsq, q) => new { Form = jfsq.Form, Section = jfsq.Section, Question = q })
.Where(f => f.Form.FormID == formId)
.GroupBy(f => f.Section.SectionID)
.Select(grp => new { SectionID = grp.Key, Questions = grp.Select(g => g.Question)});
Console.WriteLine($"For Form: {formId} the following sections with their questions were found: {String.Join(", ", result.Select(r => $"SectionID: {r.SectionID}, QuestionIDs: [{String.Join(", ", r.Questions.Select(q => q.QuestionID))}]"))}");
}
public class Form
{
public Int32 FormID { get; set; }
public Int32 SectionID { get; set; }
}
public class Section
{
public Int32 SectionID { get; set; }
public String SectionName { get; set; }
}
public class SectionQuestion
{
public Int32 SectionID { get; set; }
public Int32 QuestionID { get; set; }
}
public class Question
{
public Int32 QuestionID { get; set; }
public String Content { get; set; }
}
This will return the following result:
For Form: 4 the following sections with their questions were found: SectionID: 2, QuestionIDs: [1, 2]

Using the ALL operator in linq to filter child items of EntitySet

I have a two objects as follows:
public class Item
{
public int ItemId {get;set;}
public string ItemName {get;set;}
public List<Tag> ItemTags {get;set;}
public DateTime DateCreated {get;set;}
}
public class Tag
{
public int TagId {get;set;}
public string TagName {get;set;}
}
These are LINQ-to-SQL objects, so the ItemTags will be an EntitySet.
I am trying to perform a search query where a user can provide a comma delimited list of tags as a search filter.
How do I filter my list of items to those which contains all of the tags in the comma delimited list.
EDIT2
e.g.
Item1 has tags of Apple, Banana, Orange
Item2 has tags of Banana, Orange
Item3 has tags of Pineapple, Orange
If the tag filter is "Banana, Orange" I need the results to be Item1 and Item2.
/EDIT2
This is what I have tried thus far:
string tags = "Manchester United,European Cup,2008";
List<string> tagsList = tags.Trim().ToLower()
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.CurrentCultureIgnoreCase)
.ToList();
List<Item> itemList = ItemRepository.FetchAll();
var query = itemList
.OrderByDescending(p => p.DateCreated)
.ToList();
if (tagsList.Count() > 0)
{
query = query
.Where(p => p.ItemTags
.Select(q => q.TagName.ToLower())
.All(r => tagsList.Contains(r)))
.ToList();
}
However, this doesn't seem to work. Any ideas on what I am doing wrong please?
EDIT1: tags are trimmed and are 'lowercased'.
That because you're puting the tags from the items to lowercase, but not the searched tags.
With this modification it should work:
List<string> tagsList = tags
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.ToLower())
.Distinct()
.ToList();
EDIT: OK, I see what the problem is: you're doing it backwards. You're searching for items that have only the tags that you're looking for.
Try that instead:
query =
(from item in query
let itemTags = p.ItemTags.Select(it => it.TagName.ToLower())
where tags.All(t => itemTags.Contains(t))
select item).ToList();
UPDATE: here's a version with the lambda syntax. It's pretty ugly because of the temporary anonymous type, but that's how the let clause translates to lambda...
query =
query.Select(item => new { item, itemTags = item.ItemTags.Select(it => it.TagName.ToLower()) })
.Where(x => tagsList.All(t => x.itemTags.Contains(t)))
.Select(x => x.item)
.ToList();
I think you need to do something like this:
var query = itemList.OrderByDescending(p => p.DateCreated).ToList();
var results = query.Where(i => i.ItemTags
.All(it => tagsList.Contains(it.TagName.ToLower())));
Then results should then be a list of matching items.
PS. Your code shows you fetching itemList as a List from your repository and then sorting by date created. This means the sorting isn't being done in the database. Once you turn something into a List you give up the benefits of deferred execution as you will bring back the entire collection into memory.
EDIT: Here's the test code to prove it works in Linq to Objects:
public class Item
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public List<Tag> ItemTags { get; set; }
public DateTime DateCreated { get; set; }
}
public class Tag
{
public int TagId { get; set; }
public string TagName { get; set; }
}
class Program
{
static void Main(string[] args)
{
RunTags();
}
private static void RunTags()
{
Item i1 = new Item()
{
ItemId = 1,
ItemName = "Item1",
ItemTags = new List<Tag>() { new Tag { TagId = 1, TagName = "2008" }, new Tag { TagId = 2, TagName = "Donkey" } }
};
Item i2 = new Item()
{
ItemId = 2,
ItemName = "Item2",
ItemTags = new List<Tag>() { new Tag { TagId = 4, TagName = "Cat" }, new Tag { TagId = 2, TagName = "Donkey" }, new Tag { TagId = 3, TagName = "Seattle" } }
};
Item i3 = new Item()
{
ItemId = 3,
ItemName = "Item3",
ItemTags = new List<Tag>() { new Tag { TagId = 523, TagName = "Manchester united" }, new Tag { TagId = 10, TagName = "European Cup" }, new Tag { TagId = 1, TagName = "2008" } }
};
Item i4 = new Item()
{
ItemId = 4,
ItemName = "Item4",
ItemTags = new List<Tag>() { new Tag { TagId = 05, TagName = "Banana" }, new Tag { TagId = 140, TagName = "Foo" }, new Tag { TagId = 4, TagName = "Cat" } }
};
Item i5 = new Item()
{
ItemId = 5,
ItemName = "Item5",
ItemTags = new List<Tag>() { new Tag { TagId = 05, TagName = "Banana" }, new Tag { TagId = 140, TagName = "Foo" } }
};
List<Item> itemList = new List<Item>() { i1, i2, i3, i4, i5 };
string tags = "Manchester United,European Cup,2008";
List<string> tagsList = tags.Trim().ToLower()
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Distinct(StringComparer.CurrentCultureIgnoreCase)
.ToList();
var query = itemList
.OrderByDescending(p => p.DateCreated).ToList();
var results = query.Where(i => i.ItemTags.All(it => tagsList.Contains(it.TagName.ToLower())));
foreach (var item in results)
{
Console.WriteLine(item.ItemName); // Should return "Item3"
}
Console.ReadLine();
}
If you want to match any of the tags in the Item's ItemTag list then just change All to Any i.e.
var results = query.Where(i => i.ItemTags.Any(it => tagsList.Contains(it.TagName.ToLower())));

Resources