Display related data in Details action MVC4 - asp.net-mvc-4

I have two tables (one to many relationship) and I want to display related data from second table in Details View. Models for tables:
public partial class jprl_uplny
{
[Key]
[Column(Order = 0)]
[StringLength(255)]
public string IDPS { get; set; }
public string DC { get; set; }
[StringLength(255)]
public string CP { get; set; }
public double? PS { get; set; }
public virtual ICollection<etaze> Etaze { get; set; }
}}
public partial class etaze
{
[Key]
[Column(Order = 0)]
[StringLength(255)]
public string IDPS { get; set; }
public double? ET { get; set; }
public double? VEK { get; set; }
public double? VYM { get; set; }
}
In table "etaze" , IDPS column is foreign key for table "jprl_uplny", too.
Model "Model1" defines my dbContext
public partial class Model1 : DbContext
{
public Model1()
: base("name=Model1")
{
}
public virtual DbSet<jprl_uplny> jprl_uplny { get; set; }
public virtual DbSet<etaze> Etaze { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
After scaffolding, ActionResult Details in my controller looks like:
public ActionResult Details(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
jprl_uplny jprl_uplny = db.jprl_uplny.Find(id);
if (jprl_uplny == null)
{
return HttpNotFound();
}
return View(jprl_uplny);
}
When I click on "details" for some row in table which display´s values from "jprl_uplny" (index.cshtml), I want to display related data from "etaze" (in details.cshtml).
Can someone advise me how to relate "jprl_uplny" and "etaze" with IDPS column in my Controller in Actionresult Details (one to many relationship)?

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.

Set one to one and one to many both relationships among two tables

I have two tables called employee and team. I want to set relationships among the tables as follows.
employee belongs to a team. (1: m relationship).
team has a team leader (team leader is also an employee). (1:1 relationship)
employee table
[primary key]
public int RegistrationNumber { get; set; }
public string Name { get; set; }
public string Email { get; set; }
team table
[primary key]
public string Name { get; set; }
public string Description { get; set; }
How can I do it?
Below is a work demo, you can refer to it.
team.cs:
public class team
{
private TeamLeaderDbContext Context { get; set; }
[Key]
public string Name { get; set; }
public string Description { get; set; }
public int? leaderID { get; set; }
public employee leader { get { return Context.employees.Find(leaderID); } }
public ICollection<employee> employees { get; set; }
}
employee.cs:
public class employee
{
[Key]
public int RegistrationNumber { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
TeamLeaderDbContext:
public class TeamLeaderDbContext : DbContext
{
public TeamLeaderDbContext(DbContextOptions<TeamLeaderDbContext> options)
: base(options)
{
}
public DbSet<team> teams { get; set; }
public DbSet<employee> employees { get; set; }
}
homecontroller:
public class HomeController : Controller
{
private readonly TeamLeaderDbContext _context;
public HomeController(TeamLeaderDbContext context)
{
_context = context;
}
public IActionResult Index()
{
var team = _context.teams.Include(c => c.employees).ToList();
return View();
}
}
result:

ASP.Net core - make a search inside a nested collection

I'm trying to make a nested collection search and I'm really struggling.
My expected result is: I would like to make a search and find all the powerUp objects by a certain date. (PowerUpDate property - that's the searching criteria)
User Model:
public class AppUser : IdentityUser
{
public ICollection<Hero> Heroes { get; set; }
}
Hero Model:
[Table("Heroes")]
public class Hero
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Ability { get; set; }
[Required]
public string SuitColors { get; set; }
public double CurrentPower { get; set; }
public double StartingPower { get; set; }
public DateTime Created { get; set; } = DateTime.Now;
public ICollection<PowerUp> PowerUps { get; set; }
public AppUser AppUser { get; set; }
[Required]
public string AppUserId { get; set; }
}
PowerUp Model:
[Table("PowerUps")]
public class PowerUp
{
public int Id { get; set; }
[Required]
public double PowerUpIncrement { get; set; }
[Required]
public DateTime PowerUpDate { get; set; } = DateTime.Now;
public Hero Hero { get; set; }
[Required]
public int HeroId { get; set; }
}
DataContext:
public class DataContext : IdentityDbContext<AppUser>
{
public DataContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Hero>().HasMany(hero => hero.PowerUps).WithOne(powerUp => powerUp.Hero)
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<AppUser>().HasMany(user => user.Heroes).WithOne(hero => hero.AppUser)
.OnDelete(DeleteBehavior.Cascade);
}
}
Could someone please explain to me how can I implement such a search on a nested collection?
Inject your AppUser user using Dependency injection
(better use the repository pattern) anyway it should be something like this: user.Heroes.PowerUps.OrderBy(x=>x.PowerUpDate == Datetime.Now).ToList();
x.PowerUpDate == To whatever date you will insert

Mapping multiple properties of a same type with HasMany via automapping

I am trying to map properties of the same type on a OneToMany association. I tried to distinguish with Description but kinda stuck here.
public class User
{
public virtual int UserId { get; set; }
public virtual string UserName { get; set; }
[Description("From")]
public virtual IList<Message> FromMessageList { get; set; }
[Description("To")]
public virtual IList<Message> ToMessageList { get; set; }
}
public class Message
{
public virtual int MessageId { get; set; }
public virtual string Text { get; set; }
[Description("From")]
public virtual User FromUser { get; set; }
[Description("To")]
public virtual User ToUser { get; set; }
}
public class DefaultHasManyConvention : IHasManyConvention
{
public void Apply(IOneToManyCollectionInstance instance)
{
if (instance.OtherSide.Property.GetDescription() == instance.Member.GetDescription())
{
if (instance.Member.GetDescription() != null)
instance.Key.Column(instance.Member.GetDescription() + "Id");
else
instance.Key.Column(instance.OtherSide.Property.Name + "Id");
instance.Fetch.Select();
}
}
}
public class DefaultReferenceConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
if (instance.Property.GetDescription() != null)
instance.Column(instance.Property.GetDescription() + "Id");
else
instance.Column(instance.Property.Name + "Id");
instance.Fetch.Select();
}
}
For one to many relationships I generally use coding like :
public class User
{
public int UserId { get; set; }
public string UserName { get; set; }
[Description("From")]
public virtual ICollection<Message> FromMessageList { get; set; }
[Description("To")]
public virtual ICollection<Message> ToMessageList { get; set; }
}
public class Message
{
public int MessageId { get; set; }
public string Text { get; set; }
[Description("From")]
public virtual User FromUser { get; set; }
// From user foreign key column
[ForeignKey("FromUser")]
public int FromUserId {get;set;}
[Description("To")]
public virtual User ToUser { get; set; }
// ToUser foreign key column
[ForeignKey("ToUser")]
public int ToUserId {get;set;}
}
Try to use ICollection instead of IList - this solved many issues for me.
Add foreign key column names; it makes mapping simpler and filtering in queries easier.

Pass through multiple dbmodel to a view from a controller

I am using ASP.NET MVC 4.
I have this class:
namespace Attempt4.Models
{
public class UsersModel : DbContext
{
public UsersModel()
: base("name=UsersConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<Roles> UserRoles { get; set; }
public DbSet<UsersInRoles> UsersInUserRoles { get; set; }
}
}
and
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
Then there is another class:
public partial class FskWebInterfaceContext : DbContext
{
public FskWebInterfaceContext()
: base("name=FskWebInterfaceContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<trigger_dest_assoc> trigger_dest_assoc { get; set; }
public DbSet<ut_AccessLevel> ut_AccessLevel { get; set; }
public DbSet<ut_Client> ut_Client { get; set; }
public DbSet<ut_ContactID> ut_ContactID { get; set; }
public DbSet<ut_destinations> ut_destinations { get; set; }
public DbSet<ut_DeviceDescription> ut_DeviceDescription { get; set; }
public DbSet<ut_DeviceType> ut_DeviceType { get; set; }
public DbSet<ut_event_log> ut_event_log { get; set; }
public DbSet<ut_GMUTempData> ut_GMUTempData { get; set; }
public DbSet<ut_Triggers> ut_Triggers { get; set; }
public DbSet<ut_User> ut_User { get; set; }
public DbSet<ut_UserAPNdevices> ut_UserAPNdevices { get; set; }
public DbSet<ut_UserClientLink> ut_UserClientLink { get; set; }
}
Now I need to be able to access both of these database contexts from my view.
I know how to pass through just a model for example just UserProfile. But I need to be able to access all of the elements in these two classes.
How can i pass them through from the controller to the View.
And Specifically, once I have passed them through, how do I access them individually in the view?
You have the answer in the comments section of your question:
From what I have been reading I need to make use of a ViewModel class.
So go ahead and define a class that will contain the necessary information. Then in your controller action populate the properties of this model and have it passed to the view.
For example let's suppose that you wanted to access UserProfiles from the first context and the ut_GMUTempData from the second context:
public class MyViewModel
{
public IList<UserProfile> UserProfiles { get; set; }
public IList<ut_GMUTempData> GMUTempData { get; set; }
}
and in your controller action:
public ActionResult Index()
{
using (var ctx1 = new UsersModel())
using (var ctx2 = new FskWebInterfaceContext())
{
var model = new MyViewModel();
model.UserProfiles = ctx1.UserProfiles.ToList();
model.GMUTempData = ctx2.ut_GMUTempData.ToList();
return View(model);
}
}
and now your view becomes strongly typed to the view model and you can access both properties:
#model MyViewModel
... you could use both #Model.UserProfiles and #Model.GMUTempData collections
UPDATE:
As requested in the comments section here's how you could loop through the user profiles in the view:
#model MyViewModel
#foreach (var profile in Model.UserProfiles)
{
<div>#profile.SomePropertyOfTheUserProfileClassThatYouWantToDisplayHere</div>
}