I have some hierarchal data. The Model class I use looks like this:
public class Category
{
[Key]
public int CategoryID { get; set; }
[Required]
[StringLength(64)]
public string Name { get; set; }
public int? ParentCategoryID { get; set; }
[ForeignKey("ParentCategoryID")]
public Category ParentCategory { get; set; }
[Required]
public int ListOrder { get; set; }
// left/right
public int TreeLeft { get; set; }
public int TreeRight { get; set; }
} // eo class Category
I've used the techniques outlined here to store my data, and inserting and retrieving data is not a problem.
What I would like to do, is add a Category collection to this class:
public virtual IEnumerable<Category> {get; set; }
I've used this technique in the past (learned from the Mvc tutorials), to include related tables when getting data. However, when I tried this I received an error with regard to IEnumerable<> being abstract (which is understandable, I guess the framework couldn't figure out what I want to do)...
... and indeed, being new to LINQ, I have no idea what the LINQ would look like that would give me back a collection of Category instances each of which had their children inside them.
If it's not possible I guess I can construct the list manually, use a regular LINQ query to get all the categories at a particular position (and their children) and manually populate it all.
I was wondering if LINQ could do this for me?
Thanks in advance!
If you have a self reference fk than the collection should be generated automatically when you add the table to the dbml file
And will look something like this:
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Category_Category", Storage="Categories", ThisKey="pkCategoryID", OtherKey="ParentCategoryID")]
public EntitySet<Category> Categories
{
get
{
return this._Categories;
}
set
{
this._Categories.Assign(value);
}
}
Dont use IEnumerable<Category> but Collection<Category> . If that is your problem..
Related
I need your help. I have next simple class:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public IEnumerable<Person> People { get; set; }
}
I need to get class by ID and all children of the class that have ParentId same with ID of first class (and children of children)? I need to use LINQ filtration. Thanks for help!
Okay, there are two solutions that I could find. The first is using the recursive method on the server-side. But in this variant, you need each time request database for each level of hierarchy. The best solution is using Recursion in SQL. You need to do only one request to the database. I attach the link. https://medium.com/swlh/recursion-in-sql-explained-graphically-679f6a0f143b
I want to make a tree structured product category view. I have found this article by Ole Michelsen from 2011, which I think looks promising. The article describes a method similar to what I almost had in mind, using Razor to recursively render the tree structure.
My database table is almost identical to the one described in the article:
[ProductCategory]
Id
ParentId
Title
I'm not sure what my view model should look like. Should it be an IEnumerable of ProductCategory, or should it be an instance of ProductCategory and have an IEnumerable of ProductCategories in it?
Something like this ...
public class ViewModelProductCategory
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public int SortOrder { get; set; }
public int NumOfProducts { get; set; }
}
... or more like this?
public class ViewModelProductCategory
{
public IEnumerable<ProductCategory> ProductCategory { get; set; }
//public int NumOfProducts { get; set; }//<--Not too sure about this property
public IEnumerable<Product> Products { get; set; }
}
If the second one is closer to the "correct" one, how can I have SortOrder and NumOfProducts (how many products are in the current category)?
And the thing I'm most confused about, is how the razor rendering comes together. How do I send the viewmodel to the recursive partial view, and how does the partial view know which item to render?
I have some razor-code, but I can guarantee that posting it will NOT make anything clearer as of what I'm trying to achieve.
This pseudo-code is perhaps more describing:
_recursivePartial.cshtml
#model [my unknown viewmodel goes here, is it IEnumerable or not?]
<ul>
foreach item in model
{
<li>#Html.Partial("_recursivePartial.cshtml", [what goes here?])
// 1: How does _recursivePartial.cshtml know where in the tree it is?
// 2: How does this structure relate to the data structure in the DB?
}
</ul>
I’m not sure there is a “correct” way of doing things, but I like to keep my database models different to the view models. I often use AutoMapper to get the data between models.
In your situation I’d probably have two View Models:
public class ProductCategoryItemModel
{
public int Id { get; set; }
public int? ParentId { get; set; }
public string Title { get; set; }
public int SortOrder { get; set; }
public int NumOfProducts { get; set; }
}
and
public class ProductCategoriesModel
{
public List<ProductCategoryItemModel> Categories { get; set; }
}
I always convert ToList() rather than passing an IEnumerable to views, but again I’m not sure that’s the “correct” way.
I'm working on a recommendation algorithm which all works fine. But now I wanted to implement this code into the branch of my development team.
I'll start from the top. My algorithm can recommend 2 types of objects, restaurants and dishes.
Restaurant:
public class Restaurant
{
public Guid Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Tag> Tags { get; set; } = new List<Tag>();
public int PriceRange { get; set; }
}
And dish:
public class Dish
{
public Guid Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public virtual Restaurant rest { get; set; }
[ForeignKey("rest")]
public Guid RestaurantId { get; set; }
public List<Tag> Tags { get; set; }
}
Now my product owner wants the list to be like this when it's being presented on the home page of our app:
[Restaurant][Dish][Restaurant][Dish] Etc...
So basically, he wants to alternate the type of object that's being recommended. These dishes and restaurants are completely separate. They are generated by my algorithm purely on the user's preferences and have no correlation with eachother at all.
Now my problem is how to return such a list. I figured I'd need a wrapper class which contains either a Restaurant or Dish like this:
public class RecommenderItem
{
public Restaurant rest { get; set; }
public Dish dish { get; set; }
}
This way I can create a List<RecommenderItem> and return that to the client. The client would only need to check which attribute is null and retrieve the values from the one that is not.
I'm just unsure if this is the correct approach. Are there any 'best practices' in doing this? Let me know if I should elaborate more!
If they doesn't have common base class then creating one wrapper class is the best solution. At the same time you can be more flexible and create something like
public class RecommendationItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PageUrl { get; set; }
public object Entity { get; set; }
}
So you can include all common information in this class and client will not be required to check with which object type he works. In such case it would be easier to add one more item type. At the same type I added reference to entity itself - it can be used if some specific handling for one or two item types is required.
You can declare an interface IRecommenderItem:
public interface IRecommenderItem
{
//shared properties
}
public class Restaurant : IRecommenderItem
{
}
public class Dish : IRecommenderItem
{
}
than, you can type:
List<IRecommenderItem> m = new List<IRecommenderItem>();
If you are going to connect pairs of elements it always makes sense to me to... well, pair the elements. I am assuming that each dish is specific to a particular restaurant? So the list would be [Restaurant1][Dish for Restaurant1][Restaurant2][Dish for Restaurant2]...?
I like the previous answer by oryol creating a common base class as well.
So, your RecommenderItem class is fine. But fill in both properties and pass a list of pairs back. Expand the list into the full set of items for display by creating a new List, iterating through the list of RecommenderItems and adding Restaurant and Dish from each entry in it.
I am trying to create a list of custom objects in LINQ, and I am not sure how to do it. Here is my classes...
public class MenuModel
{
public IList<MenuCategoriesWithArticles> Menu { get; set; }
}
public class MenuCategoriesWithArticles
{
public Category Category { get; set; }
public IList<Article> Articles { get; set; }
}
and I would like to create MenuModel from the following functions that return Category and IList in order.
businessCategory.GetAllCategories();
businessArticle.GetArticlesByCategory(int categoryId);
I have something like below but I am not sure...
businessCategory.GetAllCategories().Select(x=> new .....)
any help would be great. I dont want to loop to get each categories' articles.
Maybe something like this could help you.
businessCategory.GetAllCategories().Select(x=> new MenuCategoriesWithArticles{
Category = x,
Articles = businessArticle.GetArticlesByCategory(x.categoryId).ToList();
});
The only thing is, if GetArticlesByCategory does a database search this code won't be optimal; if that is the case, you should query all the articles separately depending on the categories you select first.
I assume you are using Entity Framework.
The best approach for you will be to create a relationship between articles and category in your sql server, change your classes that represent table to have references to each other, and let you context know about it.
public class Category
{
public int CategoryId { get; set; }
public IList<Article> Articles { get; set; }
}
public class Article
{
public int ArticleId { get; set; }
public Category Category { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Article>().HasOne(article => article.Category)
.WithMany(category=> category.Articles);
}
When you have this changes, you can get your categories this way.
await dbContext.Category.Include("Articles").ToListAsync()
After executing, your Category object will have list of Articles. You can find more info here http://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
I have a couple of classes:
public class MyGoalsModel
{
[Key]
public string Name { get; set; }
/*Some local bools*/
public List<MyGoalString> myGoals { get; set; }
}
public class MyGoalString
{
public int MyGoalStringID { get; set; }
public string GoalString { get; set; }
public bool Selected { get; set; }
}
I can populate them correctly, and the code (EF?) generates the necessary hidden foreign keys to link them (all ok in SQL) and recover the information for MyGoalsModel, but the List is always null.
I use the following to get the entry I want:
MyGoalsModel goals = db.MyGoals.Find(Name);
but when I investigate the code goals.MyGoals is always null.
Am I missing something, is there a better way to recover the information with the lists present?
Add the keyword virtual so EF can create a proxy for your List and lazy load the data when needed.
Edit: Or as stated in the accepted answer in this question.