How to load master-details data(more than 2 hierarchy) using WCF RIA Services - wcf

I'm trying to get my head around treeviews and am able to do two levels, but I'm stumped with adding the 3rd level. I assume you make a 3rd Hierarchical Template - but I'm not sure how this is loaded. I'm using the AdventureWorks database as sample data.
I'm using the Product, ProductCategory, and ProductSubCategory tables.
My Metadata looks like. (just the interesting bits)
public partial class Product
{
public string Name { get; set; }
public int ProductID { get; set; }
public string ProductNumber { get;set; }
public ProductSubcategory ProductSubcategory { get; set; }
public Nullable<int> ProductSubcategoryID { get; set; }
}
public partial class ProductCategory
{
public string Name { get; set; }
public int ProductCategoryID { get; set; }
[Include]
[Composition]
public EntityCollection<ProductSubcategory> ProductSubcategory { get; set; }
}
public partial class ProductSubcategory
{
public string Name { get; set; }
[Include]
[Composition]
public EntityCollection<Product> Product { get; set; }
public ProductCategory ProductCategory { get; set; }
public int ProductCategoryID { get; set; }
public int ProductSubcategoryID { get; set; }
My Queries look like :
public IQueryable<Product> GetProduct()
{
return this.ObjectContext.Product;
}
public IQueryable<ProductCategory> GetProductCategory()
{
return this.ObjectContext.ProductCategory.Include("ProductSubcategory");
}
public IQueryable<ProductSubcategory> GetProductSubcategory()
{
return this.ObjectContext.ProductSubcategory.Include("Product");
}
My Code behind (which is where I'm having the problem understanding how to load two queries). I want to return Products under ProductSubCategory under ProductCategory.
public partial class Tree : Page
{
public Tree()
{
InitializeComponent();
AdventureWorksContext ads = new AdventureWorksContext();
trvTree.ItemsSource = ads.ProductCategories;
ads.Load(ads.GetProductCategoryQuery());
}
}

Try modifying your GetProductCategory query as such:
{
return this.ObjectContext.ProductCategory.Include("ProductSubcategory").Include("ProductSubcategory.Product");
}
I don't know if it'll work in your case, where you want to build a tree, but it should include the data as needed.

Related

How to establish one-to-many relationship for a code-first approach?

I'm trying to build a recipe app for my spouse. I'm trying to set it up so she can add new recipes to the database as the app grows.
When adding new recipe, she will have three drop-down to pick from to construct her new recipe ingredients. First one will contain a list of ingredients that she can choose from, the second one a list of measuring units and the third one a list of quantities.
Here is what I got so far. Am I heading in the right direction or am I off? I'm using Entity Framework with a code-first approach:
public class Recipes
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
public class Units model
{
[Key]
public int Id { get; set; }
public string UnitName { get; set; }
}
public class UnitQty
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class IngredientsModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class RecipeIngredients
{
public int Id { get; set; }
public int RecipesId { get; set; }
[ForeignKey("RecipesId")]
public Recipes Recipes { get; set; }
public int IngredientsModelId { get; set; }
[ForeignKey("IngredientsModelId")]
public IngredientsModel IngredientsModel { get; set; }
public int UnitQtyId { get; set; }
[ForeignKey("UnitQtyId")]
public UnitQty UnitQty { get; set; }
public int UnitsModelId { get; set; }
[ForeignKey("UnitsModelId")]
public UnitsModel UnitsModel { get; set; }
}
After creating the table, controller and the views, this is what I get in the recipe ingredients index view.
Any suggestion will be more than welcome please and thank you
RecipeIngredient class's view
First of all. You are over engineering your domain model. On relational databases Join is bottleneck you should prevent from joins if it doesn't helps you.
public class Recipt
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public ICollection<RecipeIngredient> Ingredients { get; set; }
}
public class IngredientModel
{
public int Id { get; set; }
public string Name { get; set; }
public IngredientUnit UnitType { get; set; } // Unit model is best to be added here. if it doesn't change in a single IngredientModel.
}
public class RecipeIngredient
{
public int Id { get; set; }
public int UnitQuantiy { get; set; } // No need to more classes.
public IngredientModel Model { get; set; }
public Recipt Recipt { get; set; }
}
public Enum IngredientUnitType // Same Unit Model but less database relation as its small finite collection.
{
Killogram,
Count,
....
}
and according to the Microsoft documents its best to use fluentApi configuration for the relations.
Override this method in your Context:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Recipt>.HasMany(P => P.Ingredients).WithOne(P => P.Recipt);
builder.Entity<RecipeIngredient>.HasOne(P => P.Model);
// There is no need to explicit foreign key definition. but you can explicitly define your foreign keys.
}
And for the last part. in Views you can use extra models called ViewModels.
As above domain turned to a minimal domain you just need to pass a list of IngredientModels to your view to complete your View.

How to show and search a list of products in asp.net core?

I would like to build these functionalities to a project using Asp.Net Core MVC.
Could someone please guide me through, How I can approach these steps:
View a list of product types for a given product category or for all categories.
I have created an ASP.NET Core MVC project with Identity authentication, where the user could register and log in.
I also have these Models created.
namespace Company.Models
{
public class ProductType
{
public ProductType()
{
Products = new List<Product>();
}
public long ProductTypeId { get; set; }
public string ProductName { get; set; }
public string ProductInfo { get; set; }
public string Location { get; set; }
public ProductTypeStatus Status { get; set; }
public string ImageUrl { get; set; }
public string Manufacturer { get; set; }
public string AdminComment { get; set; }
public Category Categories { get; set; }
public ICollection<Product> Products { get; protected set; }
}
public enum ProductTypeStatus
{
Available,
ReservedAdmin
}
public enum ProductStatus
{
Available,
ReservedLoaner,
ReservedAdmin,
Loaned,
Defect,
Trashed,
Lost,
NeverReturned
}
namespace Company.Models
{
public class Product
{
public long ProductId { get; set; }
public long ProductTypeId { get; set; }
public int ProductNumber { get; set; }
public string SerialNo { get; set; }
public ProductStatus Status { get; set; }
public string AdminComment { get; set; }
public string UserComment { get; set; }
public long? CurrentLoanInformationId { get; set; }
}
}
namespace Company.Models
{
public class Category
{
public Category()
{
ProductTypes = new List<ProductType>();
}
public int CategoryId { get; set; }
public string Name { get; set; }
public ICollection<ProductType> ProductTypes
{
get; protected set;
}
}
I have recently turned to Asp.Net Core MVC. So this is a new envirnoment for me to get startd. Though, I did follow the msdn tutorials on asp.net mvc.
I APPRECIATE any help!
I saw your model design I think you missing 1 small thing that is relationship between Product and Category.
1 Product will be in 1 Category
So to add 1 to 1 relationship you need to adjust your model like this. You can view more here
namespace Company.Models
{
public class Product
{
public long ProductId { get; set; }
public long ProductTypeId { get; set; }
public int ProductNumber { get; set; }
public string SerialNo { get; set; }
public ProductStatus Status { get; set; }
public string AdminComment { get; set; }
public string UserComment { get; set; }
public long? CurrentLoanInformationId { get; set; }
public Category Category { get;set; }
}
}
namespace Company.Models
{
public class Category
{
public Category()
{
ProductTypes = new List<ProductType>();
}
public int CategoryId { get; set; }
public string Name { get; set; }
public ICollection<ProductType> ProductTypes
{
get; protected set;
}
}
}
So when you update your model you will need to run ef migration to apply change to db. Detail can be found here
And finally you need to write the code to query some thing like
var query = _db.Product.Where(x => x.Category == "Book");
You can read how to write ef query in c# here

Querying a table that relates to multiple entity types

So currently I have an application model of:
Note -> Thing
(A note can relate to many things)
A thing can be numerous entities (for this example lets use Computer & Car)
e.g
Note -> Computer
-> Car
So right now, I have the schema of
Note -> ComputerNote -> Computer
Note -> CarNote -> Car
The problem is that because the entity links are in separate tables, it requires a new query to be written rather than just using filtering in the WHERE clause.
Ideally it would be nice to have an EntityId & EntityTypeId column & on the Note table that would hold the primary key of the related entity and the type of the entity. Thus application logic could look for all Car notes where the car is x without a separate query for each type, but.. this would mean I lose referential integrity. Is there a better way, or is what I have suggested an acceptable design?
Entity Framework Model's:
public partial class Note
{
public Note()
{
NoteComputer = new HashSet<NoteComputer>();
NoteCar = new HashSet<NoteCar>();
NoteThing = new HashSet<NoteThing>();
}
public int Id { get; set; }
public string Value { get; set; }
public string CreatedByUserId { get; set; }
public DateTime CreatedDateTime { get; set; }
public ICollection<NoteComputer> NoteComputer { get; set; }
public ICollection<NoteCar> NoteCar { get; set; }
public ICollection<NoteThing> NoteThing { get; set; }
}
public partial class NoteCar
{
public int Id { get; set; }
public int NoteId { get; set; }
public int CarId { get; set; }
public Car Car { get; set; }
public Note Note { get; set; }
}
public partial class NoteComputer
{
public int Id { get; set; }
public int NoteId { get; set; }
public int ComputerId { get; set; }
public Computer Computer { get; set; }
public Note Note { get; set; }
}
public partial class NoteThing
{
public int Id { get; set; }
public int NoteId { get; set; }
public int ThingId { get; set; }
public Thing Thing { get; set; }
public Note Note { get; set; }
}
As there seems to be no nice way to handle this at the database level, I've found it best to handle this at the application level using the concrete type database schema, to produce dynamic joins.
Example in Entity Framework Core:
public GenericEntityProvider
{
private readonly IEnumerable<IEntityProvider> _entityProviders;
private readonly DatabaseContext _context;
public GenericEntityProvider(IEnumerable<IEntityProvider> entityProviders, DatabaseContext context)
{
_entityProviders = entityProviders;
_context = context;
}
public IEnumerable<Note> Get(Type type, int id) {
var provider = _entityProviders.GetPredicate(type, id);
return _context.Notes.Where(provider);
}
}
public CarNoteProvider : IEntityProvider
{
public Expression<Func<Note, bool>> GetPredicate(Type type, int id)
{
return x => x.CarNote.Any(cn => cn.CarId == id);
}
}

Automapper generates left join in SQL

I'm using Automapper in my .NET Core 2.2 back-end service. I use ProjectTo method to generate my result.
This is my Product class:
public class Product
{
public DateTime? SellEndDate { get; set; }
public string Name { get; set; }
public bool AllowToShow { get; set; }
public Category Category { get; set; }
public Guid CategoryId { get; set; }
public Brand Brand { get; set; }
public Guid BrandId { get; set; }
}
And it is the result class:
public class Dto
{
public string Name { get; set; }
public CategoryDto Category { get; set;}
public BrandDto Brand { get; set; }
}
The configuration in the profile is a normal one. The generated SQL statement for category table has Inner Join, but for brand table it uses a Left Join.
Why is that?

Handling document relationships with T[] instead of T using RavenDB

RavenDB docs show how to deal with document relationships in this sample using Includes.
public class Order
{
public Product[] Items { get; set; }
public string CustomerId { get; set; }
public double TotalPrice { get; set; }
}
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public string[] Images { get; set; }
public double Price { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string Address { get; set; }
public short Age { get; set; }
public string HashedPassword { get; set; }
}
How would I deal with Includes or Live Projections if I don't want to include the customer using Includes/Live Projections but a list of products instead:
public class Order
{
public string[] ItemIds { get; set; }
public string CustomerId { get; set; }
public double TotalPrice { get; set; }
}
If I understand what you're asking, this should help. I blogged about it here:
http://inaspiralarray.blogspot.com/2012/03/keeping-domain-model-pure-with-ravendb.html
Does that help?