I am working on an edit view that allows a user to edit a particular entity. One of the drop down menus needs to allow the user to create a new instance of a different related entity if they don't see one that exists already. I'm trying to figure out the best practice for this.
The model they are editing:
public class SurveyProgramModel
{
[Key]
public int ProgramId { get; set; }
[DisplayName("Year")]
public int ProgramYear { get; set; }
[DisplayName("Status")]
public int ProgramStatusId { get; set; }
[DisplayName("Program Title")]
public string ProgramTitle { get; set; }
public int ProgramTypeId { get; set; }
[DisplayName("Program Type")]
public virtual SurveyProgramTypeModel ProgramType { get; set; }
[DisplayName("Status")]
public virtual ProgramStatusModel ProgramStatusModel { get; set; }
public virtual ICollection<SurveyResponseModel> SurveyResponseModels { get; set; }
}
If the user does not see a ProgramType that fits what they want, they need to have an empty text box that allows them to create a new ProgramType.
Here is the ProgramType model:
public class SurveyProgramTypeModel
{
[Key]
public int ProgramTypeId { get; set; }
[DisplayName("Program Type")]
public string ProgramType { get; set; }
public virtual ICollection<SurveyProgramModel> SurveyProgramModels { get; set; }
}
What is the best practice for updating 2 models in a single submission? How do I keep my view Strongly Typed to SurveyProgramModel? Create a View Model?
You already know the answer, you would create a View Model and make the necessary changes in your HttpPost action.
Related
I'm trying to think of a way to store actual templates of ticket items in my Entity Framework MVC project. The thing is, I've already done a Code First migration process in the past. What I need to do is create logic in my code to allow someone to save time creating a ticket by using pre-loaded data from a template. My current inheritance model uses an abstract class (MasterTicket) which is used as the parent since to me there can be multiple categories (a Google Calendar based task, "Appointment Task" and a purely internal task, "General Task"). Here's my parent abstract class:
[Table("Ticket")]
[ModelBinder(typeof(MasterTicketBinder))]
public abstract class MasterTicket
{
[Key]
public Guid id{ get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ART { get; set; }
public DateTime openTime{ get; set; }
public DateTime? closeTime { get; set; }
private bool active = true;
public bool Active{ get => active; set => active = value; }
public string summary{ get; set; }
public string description{ get; set; }
public DateTime updateTime{ get; set; }
//TODO: Create foreign key relationship to user model
public Guid userUpdateId{ get; set; }
//TODO: Create foreign key relationship for tickets from other systems
public Guid externalAppId{ get; set; }
//TODO: Create foreign key relationship to user model
public Guid userOpenId{ get; set; }
public Guid? userCloseId { get; set; }
public Guid userOwnerId{ get; set; }
private int timesUpdated = 0;
public int TimesUpdated { get => timesUpdated; set => timesUpdated = value; }
public DateTime expectedCompletionTime{ get; set; }
public DateTime actualCompletionTime{ get; set; }
public List<MasterTicketItem> masterTicketItems{ get; set; }
public MasterTicket()
{
}
}
An here's an example of the concrete Google Calendar-based "Appointment Task" child:
[Table("AppointmentTickets")]
public class ApptTaskTicket : MasterTicket
{
public DateTime currentApptTime { get; set; }
public DateTime? endApptTime { get; set; }
public bool allDay { get; set; }
public string customerName { get; set; }
//TODO: Create foreign relationship
public Guid subjectPrsnlId { get; set; }
public string gCalEventId { get; set; }
public string customerPhone { get; set; }
public string customerEmail { get; set; }
public string preferredContactMethod { get; set; }
public List<ApptConfirmItem> apptConfirmItems { get; set; }
}
I know I can easily create a column for the MasterTicket class to indicate that it's a template, but to me I feel it's cleaner to have a separate "Template Table" if you will that will store pre-existing values that can be filled in with a form. In this case, I think I would WANT to create a duplicate class that would store said templates so that there are only several rows. What would be the best way to do this with Code First? Does someone feel I should take a different approach? Maybe DB First is a better way to go?
In case it matters, here's my DBContext for the Tickets:
// Code-Based Configuration and Dependency resolution
[DbConfigurationType(typeof(MySqlEFConfiguration))]
public class TicketDB : DbContext
{
public TicketDB(): base("AffirmativeServiceSystem.Properties.Settings.AffirmTaskManager")
{
}
public DbSet<MasterTicket> tickets { get; set; }
public DbSet<MasterTicketItem> ticketItems { get; set; }
}
Suppose I have two entities, bungalows and apartments. Both of them have varying fields and cannot be interchanged however both these entities have multiple tenants. Each tenant can only be part of either one bungalow or one apartment. How do I achieve this using Entity Framework?
I was thinking of creating 2 more entities bungalowTenants and apartmentTenants and using these to map. Each bungalowTenant would have one instance of a bungalow and a tenant and similarly for apartmentTenant.
Bungalows would have a collection of bungalowTenants and apartment of apartmentTenants.
public class Bungalow
{
public int Id { get; set; }
public int HouseNumber { get; set; }
public string Street { get; set; }
public ICollection<BungalowTenants> Tenants { get; set; }
}
public class Apartment
{
public int Id { get; set; }
public int ApartmentNumber{ get; set; }
public string Wing{ get; set; }
public string Building{ get; set; }
public ICollection<ApartmentTenants> Tenants { get; set; }
}
public class Tenant
{
public int Id{ get; set; }
public string Name{ get; set; }
}
public class ApartmentTenants
{
public int ApartmentId { get; set; }
public Apartment Apartment{ get; set; }
public int TenantId{ get; set; }
public Tenant Tenant{ get; set; }
}
public class BungalowTenants
{
public int BungalowId{ get; set; }
public Bungalow Bungalow{ get; set; }
public int TenantId{ get; set; }
public Tenant Tenant{ get; set; }
}
The problem with this approach is that it does not restrict in any way the same tenant to be a part of both, a bungalow and an apartment. I am unable to figure out how to do that using Entity Framework. I'd appreciate any help on this matter.
Not every business rule can be or needs to be translated to database constraints or model constraints.
And if you would enforce this, through model rules or programmed rules:
What if the tenants decide to move from a bungalow to an apartment? They will most probably want to start renting the new home days or even weeks before the cancellation date of the old one - or do you expect them to vacate the old home before midnight and enter the new home after midnight, with all their belongings packed in boxes on the pavement for a certain period? That does not seem very realistic.
I have a relatively complex relationship I need to set up between a User object and a lot of lookup tables. The user object is your run of the mill user model:
public class Youth : IAuditInfo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public Guid YouthGuid { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public string ImageName { get; set; }
[ForeignKey("FkYouthId")]
public ICollection<User> Parents { get; set; }
public CubPack Pack { get; set; }
public virtual ICollection<RequirementsLog> RequirementsLogs { get; set; }
public Youth()
{
Parents = new List<User>();
}
}
The lookup tables is where it gets complex and I can't figure out the path of least complexity in binding them together. For the lookups it is a series of tables starting with one 'master' table, that rolls down hierarchically to requirements and sub requirements, like this:
Master:
public class BearTrail
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<BearTrailRequiredBadge> BearTrailRequiredBadges { get; set; }
public virtual ICollection<BearTrailElectiveBadge> BearTrailElectivedBadges { get; set; }
}
Required Badges:
public class BearTrailRequiredBadge
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int Number { get; set; }
public string Description { get; set; }
public virtual ICollection<BearTrailRequiredBadgeSubRequirement> BearTrailRequiredBadgeSubRequirements { get; set; }
}
Required Badge sub requirement:
public class BearTrailRequiredBadgeSubRequirement
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Number { get; set; }
public string Text { get; set; }
public bool Required { get; set; }
}
This is one set of the lookups, there are about four nested classes like this, and some one off tables as well. Total lookup tables is about 16, give or take.
I was initially thinking if using my RequirementLog model to bind it:
public class RequirementsLog
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public virtual ICollection<Youth> Youth { get; set; }
public BearTrail BearTrailRequirements { get; set; }
public TigerTrail TigerTrailRequirements { get; set; }
public WolfTrail WolfTrailRequirements { get; set; }
public WebelosTrail WebelosTrailRequirements { get; set; }
public WebelosArrowOfLight WebelosArrowOfLightRequirements { get; set; }
}
So there is a many to many between RequirementsLog and Youth. The table created out of RequirementsLog has one PK column (ID), and FK columns for each property. The many to many table created out of this (RequirementsLogYouths) has two PKs (RequirementsLogId, and YouthId).
Am I going about this the right way? The end goal is to have the 16 or so tables server as just lists of various requirements, and have another table(s) to track a particular youths progress through the requirements. I have a hard time visualizes some of this DBA stuff, so any input would be greatly appreciated.
In most cases, a requirements "log" be in a one (people) to many (the log).
Unless... One logged item is for many kids...
If so, the you need a third table, that maps many people to multiple logged events. That is, if this is truly a many to many. In general, that situation almost always begs for a third, intermediate mapping table. Read up a bit on many to many designs, and you'll quickly see it, and how simple it is.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Entity1>()
.HasMany(b => b.Entities2)
.WithMany(p => p.Entities1)
.Map(m =>
{
m.ToTable("Entitie1Entity2");
m.MapLeftKey("Entity1Id");
m.MapRightKey("Entity2Id");
});
}
I have four MVC model layer domain classes.
namespace MvcMobile.Models.BusinessObject
{
public class Speaker
{
public int SpeakerID { get; set; }
public string SpeakerName { get; set; }
}
public class Tag
{
public int TagID { get; set; }
public string TagName { get; set; }
}
public class Seminar
{
public string Seminar_Code { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Room { get; set; }
}
public class Seminar_Detail
{
public string Seminar_Code { get; set; }
public int SpeakerID { get; set; }
public int TagID { get; set; }
public string DateAndTime { get; set; }
}
}
I would like to make CRUD operation by using these classes. So I create two VeiwModel Classes.
namespace MvcMobile.ViewModel
{
public class Seminar_Root_ViewModel
{
public Seminar_Subsidiary_ViewModel Seminars { get; set; }
public List<Speaker> Speakers { get; set; }
public List<Tag> Tags { get; set; }
}
public class Seminar_Subsidiary_ViewModel
{
public Seminar Seminar { get; set; }
public List<Seminar_Detail> Seminar_Detail { get; set; }
}
}
For Controller layer, I consider that I will use Seminar_Root_ViewModel to make the whole CRUD operation processes.
What I would like to ask is that Is this proper way or correct way?
If you have more elegant way to make model layer and ViewModel layer, Please let me get suggestion.
Every suggestion will be appreciated.
[updated]
Let's assume that I make master-Detail form design.
Speaker and Tag are just look-up tables for dropdownlist or some controls like that.
Seminar is Master Data and Seminar_Detail will be Item Grid Data.
So As for this scenario, all of this classes are needed for this program.
Please let me know if my thinking is wrong.
The only thing I can see is if you are not going to re-use your Seminar_Subsidiary_ViewModel view model you could skip it.
If you are going to need those two properties Seminar and Seminar_Detail on another view or ajax call, it's perfectly fine to have that kind of separation.
Personally I'm not a huge fan of _ on class name, but that have nothing to do with the question.
Consider this Poco:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Fullname { get; set; }
}
Now i want to implement a follow technique where a user may follow other users so basically its self Many to Many relationship
problem is i don't know how exactly i can achieve this in Entity Framework Code-First ?
I thought of a linker Table :
public class UserFollow
{
public int Id { get; set; }
public int Follower { get; set; }
public int Following { get; set; }
public DateTime FollowDate { get; set; }
}
i want to be able to get All Followers and Following from every User Object?
This is quite simple using EF code-first as you only need the User POCO:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Fullname { get; set; }
public ICollection<User> FollowedUsers { get; set; }
}
The collection means that a User is related to other users.
PS: I noted you added a timestamp in your solution example. To achieve that you should still add the collection changing the generic type to whatever suits your needs.
Hope it helps.