I am learning ASP.NET and trying to create two table using code first approach using MVC. Below is the model .cs file for Courses.
public class Instructor
{
[Key]
public string name { get; set; }
public string address { get; set; }
public string address_ { get; set; }
public string email { get; set; }
}
public class Course
{
[Key]
[DisplayName("Course")]
[Required(ErrorMessage = "CSExxx")]
public string progId { get; set; }
public string subject { get; set; }
public string semester { get; set; }
public string description { get; set; }
[ForeignKey("instructor")]
public virtual string name { get; set; }
public virtual Instructor instructor { get; set; }
}
I added the corresponding controller and as expected views got generated automatically by visual studio. Once I ran the project and clicked on instructor menu below is the window which got opened.
Clearly I am not able to see the column name which I declared as PK. Now when I click on Create New then I am able to see four columns including the Primary key column which is name.
My Question why I am not able to see the primary key column in the main display.
The templates and code generators at work here assume a technical key, ie one that is not visible or meaningful to the user.
Your choice of name is debatable, the simple solution here is to introduce
[Key]
public int Id { get; set; }
in all your classes. If you do want to stick to the name, then simply edit the generated cshtml.
Related
I am new to MVC and was trying to get the Scaffolding to automagically create the drop down list in the PersonTitle for Person and Title. I got the drop down list to work however, the scaffolding function takes the first instance of a string as the value of the drop down. As in the case of the Person, the first name is used. However, that is not very informative.
I want to be able to modified it to contain the First and Last name. What is the best solution for this? I tried adding a FullName field but that has its own set of problems. Once of them being, I don't want the program/user to handle extra data entries.
Is there a better method of creating the drop down list for Person and Title after the scaffolding completes? What is the best way to add foreign key drop down list from other tables?
It would help if you provide code samples as I am new to MVC and the best practices solution as I would have to do this to several other tables.
Thanks much.
A person can have many titles
// Title -->>PersonTitle<<<----Person
public class PersonTitle
{
//person can have many titles
public int PersonTitleID { get; set; }
public int PersonID { get; set; }
public int TitleID { get; set; }
public virtual Person Person { get; set; }
public virtual Title Title { get; set; }
}
List of Titles
public class Title
{
public int TitleID { get; set; }
[Display(Name = "Title Name")]
public string TitleName { get; set; } //drop down text
public virtual ICollection<PersonTitle> PersonTitles { get; set; }
}
List of People
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; } //drop down text is used
public string LastName { get; set; }
public virtual ICollection<PersonTitle> PersonTitles { get; set; }
}
As a new programmer I am trying to understand when I should create navigation properties for my Models. What are the trade offs?
On the extremes, the model can just contain ever field need, or the base model can have navigation properties for every field?
Or should navigation property only be used for complex related entities (an entity with more than one property)?
Another consideration I am considering is what works best for MVC drop down or jquery autocomplete. How will designing the model impact application and sql performance?
public class Vendor
{
public int ID { get; set; }
public string Name { get; set; }
public string Number { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
or I could do this and assume the related tables also exists in the namespace and in turn the database.
public class Vendor
{
public int ID { get; set; }
public virtual Name Name { get; set; }
public virtual Number Number { get; set; }
public virtual Street Street { get; set; }
public virtual City City { get; set; }
public virtual State State { get; set; }
public virtual PostalCode PostalCode { get; set; }
public virtual Country Country { get; set; }
}
I can see that some of the related entities will be static in nature like States but Number and Street will grow over time.
If your property can be represented by a simple database column, then you use the first approach, if you property itself has its own properties, then you will need a navigational property. If your case, if the City also has properties such as Id, Name, etc, then you will use the navigation property, however, if you only want to store city as the name, your first approach will work.
I'm trying to create a model that can optionally refer to a parent of the same type, for example:
public class Category
{
public virtual long CategoryID { get; set; }
public virtual Category? ParentCategory { get; set; }
public virtual int UserID { get; set; }
public virtual string Name { get; set; }
}
As you can see there is an optional member called ParentCategory that is optional and refers to a class of type Category (i.e. the same type). As I'm sure you can guess, I'm trying to create a simple Category tree, where the root node(s) will not have a parent.
This results in the following error when the Entity Framework tries to create the database:
"The ForeignKeyAttribute on property 'ParentCategoryID' on type 'MyProject.Models.Category' is not valid. The navigation property 'Category' was not found on the dependent type 'MyProject.Models.Category'. The Name value should be a valid navigation property name."
I also tried this:
public class Category
{
public virtual long CategoryID { get; set; }
[ForeignKey("Category")]
public virtual long? ParentCategoryID { get; set; }
public virtual int UserID { get; set; }
public virtual string Name { get; set; }
}
But again this resulted in the same error.
Is it possible to model this using EF Code First? Its easy to model it int he database if I were to create the database manually.
Thanks in advance
Ben
Your first example wouldn't even compile because T?, a shortcut for Nullable<T> can only be applied to value types.
The following works fine here:
public class Category
{
public virtual long CategoryID { get; set; }
public virtual Category ParentCategory { get; set; }
}
Now, this will use an ugly name by default for the FK, ParentCategory_CategoryID.
This is a way to get a nicer name, plus some flexibility when using it:
public class Category
{
public virtual long CategoryID { get; set; }
[ForeignKey("ParentCategoryID")]
public virtual Category ParentCategory { get; set; }
public virtual long? ParentCategoryID { get; set; }
}
I'm very new to ASP.NET and could use some help.
For this scenario, I have 2 classes. One is a "project" class and the other is a "company" class. Essentially, what I need is one single "company directory" of all the companies we have relationships with, but I need to be able to freely slot them into 3 different slots within a project. It is possible that the same company could occupy all 3 slots, but it's equally likely that a different company will be placed in each slot.
Here are my classes:
public class Project
{
public int ID { get; set; }
public string Name { get; set; }
public int ClientID { get; set; }
public int PublisherID { get; set; }
public int DeveloperID { get; set; }
public Company Client { get; set; }
public Company Publisher { get; set; }
public Company Developer { get; set; }
}
public class Company
{
public int ID { get; set; }
public string Name { get; set; }
}
When I have used this basic outline in the past, the complex types I specify in the bottom half of the model definition will be auto generated based on the matching int ID properties specified earlier. For example, If I had a complex type "User" that was drawing it's data from a user table in my database, specifying (int UserID) within my class followed by (User User), the UserID field would be the actual field in my project table and the User object I specify will automatically be an object containing all the User information from the user table.
Using this method as I did in the classes specified above, however, does not work in the way I expected and instead creates not only ClientID, PublisherID, and DeveloperID but also creates CompanyID, CompanyID1, and CompanyID2 which are the fields that will actually be used when attempting to instantiate the Company objects I specified (even though those fields will contain null always).
Is there any way around this?
You just need to specify that your int properties are the foreign keys to your navigation properties.
public class Project
{
public int ID { get; set; }
public string Name { get; set; }
public int ClientID { get; set; }
public int PublisherID { get; set; }
public int DeveloperID { get; set; }
[ForeignKey("ClientID")]
public Company Client { get; set; }
[ForeignKey("PublisherID")]
public Company Publisher { get; set; }
[ForeignKey("DeveloperID")]
public Company Developer { get; set; }
}
I have a code-first, POCO project in which I am trying to adjust an existing database so that it syncs up with what EF is expecting, given my existing model.
I have these entities:
public class FlaggedDate
{
[Key]
public long scheduledDayID { get; set; }
[Required]
public DateTime date { get; set; }
[StringLength(50)]
[Required]
public string dateStatus { get; set; }
[Required]
public bool isVisit { get; set; }
[Required]
public bool hasAvailableSlots { get; set; }
[Required]
public bool hasInterviewsScheduled { get; set; }
// navigation properties
public ICollection<ScheduledSchool> scheduledSchool { get; set; }
public ICollection<Interview> interviews { get; set; }
public ICollection<PartialDayAvailableBlock> partialDayAvailableBlocks { get; set; }
public Visit visit { get; set; }
public ICollection<Event> events { get; set; }
}
and
public class Visit
{
[Key]
public long flaggedDateScheduledDayID { get; set; }
[Required]
public bool isFullDay { get; set; }
// navigation property
public FlaggedDate flaggedDate { get; set; }
}
The relationship between these two is 1 : 0|1 -- i.e., FlaggedDate will exist but it may or may not have a corresponding single Visit object.
EF thinks, based on this model, that FlaggedDate should have an extra field, visit_flaggedDateScheduledDayID, which is nullable. I finally realized why: it thinks the Visit field, flaggedDateScheduledDayID, is an identity column. It's not supposed to be an identity column; it's supposed to be a foreign key that connects to FlaggedDate.
I think it does this by convention: I remember reading something to the effect that in CTP4, any field that is a single key and is int or long is assumed to be an identity column.
Is there any way I can tell EF that this is NOT an identity column? I tried fiddling with the Fluent API, but it's a mystery to me, and there are no data annotations that you can use for this.
Or, alternatively, is there any way I can fiddle with the navigation properties to get this to come out right?
If you're using mapping files with fluent API
this.Property(t => t.Id)
.HasColumnName("Site_ID")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
I would imagine it should also work declaratively
[HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)]
although I didn't try that.
I discovered I can override the identity behavior with this code:
modelBuilder.Entity<Visit>().Property(v => v.flaggedDateScheduledDayID).StoreGeneratedPattern = System.Data.Metadata.Edm.StoreGeneratedPattern.None;
However, it is still not making it a foreign key. I guess that's a different question, though. It seems setting the StoreGeneratedPattern to None is the way to override the default behavior.