I am using code first in asp mvc and i came across a situation where i need to have a model/table with a computed primary key for example:
public class Student
{
[Key]
public string StudentNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime RegistrationDate { get; set; }
}
So is there a way to make the StudentNumber to be computed by for example taking 1st letter of the LastName, the year of registration and an autoincrement number?
For performance reasons, you really don't want to have your primary key as a string, so question where this requirement is coming from. However:
[Key]
public int Id { get; set; }
[NotMapped]
public string StudentId
{
get
{
return string.Format("{0}{1}{2}",
this.LastName.Substring(0, 1),
this.RegistrationDate.Year,
this.Id);
}
}
Related
i am trying to define a database model in code-first to see and display which user is assigned as a specialist for the record data.
I have a very simple model for the user:
public class User
{
public int ID { get; set; }
public string userName { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
....
}
Next I have defined two (simple) models which define the data that can be edited by the user and the specialist should be assigned to using a dropdownlist:
public class Order
{
public int ID { get; set; }
public string orderNumber { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
public class Part
{
public int ID { get; set; }
public string partNumber { get; set; }
public string description { get; set; }
public int specialistID { get; set; }
public virtual User specialist{ get; set; }
}
What kind of relation between the models can be used without having a navigation property for each table in the User model?
Do I need to use additional tables to define the relationship: User.Id-Order.specialistID and the relationship: User.Id-Part.specialistID ?
Is there a smarter way out-of-the-box by Entity Framework?
Many thanks for your answers.
Pascal
By default when you add forign-key constraint to the many-to-one table the Entity Framework add virtual property to the entity class and virtual ICollection to the User.
The model Survey CRUD's the Questions:
public class Survey
{
public int SurveyID { get; set; }
public string Question1 { get; set; }
public string Question2 { get; set; }
public string Question3 { get; set; }
public string Question4 { get; set; }
public string Question5 { get; set; }
}
This model IntroResponse should have Properties that should be set to the values set in Survey. (IntroResponse is read only, not Creating or Editing Question properties):
public class IntroResponse : IValidatableObject
{
public int IntroResponseID { get; set; }
public int SurveyID { get; set; }
[ForeignKey("SurveyID")]
public virtual Survey Survey { get; set; }
public string Question1 { get; set; }
public string Question2 { get; set; }
public string Question3 { get; set; }
public string Question4 { get; set; }
public string Question5 { get; set; }
public IntroResponse()
{
//Code here?
}
As you can see these two models have a realtionship that is:
SurveyID 1 -----> * IntroResponse
But I want to inherit more properties from the Survey model. Is this possible without adding Controller code at all?
Shall I retrieve this information via Entity Framework or simply get values from Database?
I could not find any earlier threads about this specific question. I really looked.
Please give me an idea about what is the best practices to achieve this.
Update:
What I want to have is the Questions automatically retrieved and displayed when I select SurveyID with the dropdown. This would require client-side code, right? So should I have JavaScript code make a database call to get the Questions? I don't want to mix JavaScript and C#/Razor code in this way. That is why I am asking for some pointer!
I'm using VS 2010 with Razor/MVC 3 to create a form where User 1 submits information to a database using RequestQueue Model (this is just a queue table). User 2 then pulls this information, approves it, and the data is sent to the main database via DbRequestForm Model. This model, however, consists of several sub-models (Data_Dictionary, SERVER_DATABASE, and DatabaseRequestInfo) because the submitted data needs to go to three separate tables.
The problems is, whenever I approve the data for submission from RequestQueue to DbRequestForm, I get an error saying there is no primary key for DbRequestForm. However, there is a PK for each sub-model. I have also tried adding [Key] public int SrvrDB_ID { get; set; } and other variations to DbRequestForm to no avail.
Initial Model:
public class RequestQueue
{
[Key]
public int SrvrDB_ID { get; set; }
public string dbName { get; set; }
public int InitialSpaceNeeded { get; set; }
public string ScheduledJobSetup { get; set; }
public string PII_data { get; set; }
}
Encapsulating Model:
public class DbRequestForm
{
public Data_Dictionary Data_Dictionary { get; set; }
public DatabaseRequestInfo DatabaseRequestInfo { get; set; }
public SERVER_DATABASE SERVER_DATABASE { get; set; }
}
Models based on final three tables:
public class Data_Dictionary
{
[Key]
public int SrvrDB_ID { get; set; }
public string PII_data { get; set; }
}
public class SERVER_DATABASE
{
[Key]
public int SrvrDB_ID { get; set; }
public string dbName { get; set; }
}
public class DatabaseRequestInfo
{
[Key]
public int SrvrDB_ID { get; set; }
public int InitialSpaceNeeded { get; set; }
public string ScheduledJobSetup { get; set; }
}
Any ideas how to avoid this error? Thanks in advance!
EDIT: The specific error is '
System.Data.Edm.EdmEntityType: : EntityType 'DbRequestForm' has no key
defined. Define the key for this EntityType.
System.Data.Edm.EdmEntitySet: EntityType: EntitySet DbRequestForms is
based on type DbRequestForm that has no keys '
The error tells that you need to define key for DBRequestForm.
Code First would infer that a property is a primary key if the property is called ‘Id’ or ‘class name Id’.
In your case you have to add
[Key]
public int DBRequestFormId { get; set; }
This concrete error won't appear anymore.
here is detailed information how code first works
http://blogs.msdn.com/b/efdesign/archive/2010/06/01/conventions-for-code-first.aspx
see the Primary Key section
public class Slider_Locale
{
[Key]
public int Slider_LocaleID { get; set; }
[ForeignKey("Culture")]
public int CultureID { get; set; }
public string Slogan { get; set; }
public virtual Culture Culture { get; set; }
}
public class Culture
{
[Key]
public int CultureID { get; set; }
public string CultureName { get; set; }
public string DisplayName { get; set; }
public virtual Slider_Locale slider_Locale { get; set; }
}
It gives error as follows:
One or more validation errors were detected during model generation:
System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role
'Slider_Locale_Culture_Source' in relationship
'Slider_Locale_Culture'. Because the Dependent Role properties are not
the key properties, the upper bound of the multiplicity of the
Dependent Role must be �*�.
How could I design the relationship?. Please help me as I am newbie in mvc and entity.
This is one of those things that's a little tricky to wrap your brain around at first. The issue is that you're trying to set up a 1:1 (or 1:0) mapping, but there's nothing in your model to enforce that kind of mapping. For example, what if you have more than one Slider_Locale object with the same CultureID value? How would your application know which one to pick?
Now, you might know that this will never happen, but the Entity Framework doesn't, and it has to err on the side of caution, so it won't let you set up a relationship that it can't prove is consistent with the table structure. Ideally, it would let you specify unique constraints other than a primary key to work around this, and maybe someday it will, but for now the simplest way around this is to change it to a one-to-many mapping. For example, you could do:
public class Slider_Locale
{
[Key]
public int Slider_LocaleID { get; set; }
[ForeignKey("Culture")]
public int CultureID { get; set; }
public string Slogan { get; set; }
public virtual Culture Culture { get; set; }
}
public class Culture
{
[Key]
public int CultureID { get; set; }
public string CultureName { get; set; }
public string DisplayName { get; set; }
// Note that this got changed to ICollection<>
public virtual ICollection<Slider_Locale> slider_Locales { get; set; }
}
Another thing you could do is change the classes so that they share the same primary key values, but in order to do that you'll have to make at least one of the relationships optional. I could give an example of this if you let me know whether Slider_Locale.Culture can be null, or Culture.slider_Locale, or both.
I'm experimenting with Entity Framework 4 Code First.
I have my (simplified) models set up like this.
public class Entry
{
public int Id { get; set; }
[Required]
public virtual EntryTag Tag { get; set; }
[Required]
public int TagId { get; set; }
[Required]
public string UserId { get; set; }
}
public class EntryTag
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Color { get; set; }
[Required]
public string UserId { get; set; }
}
The user can create a new Entry, and in the same time create or re-use an EntryTag. I try to find an already existing EntryTag based on the name and userId.
var tag = ResolveTag(entry.Tag.Name, entry.UserId);
entry.Tag = tag == null ? AddTagBasedOn(entry) : tag;
_entryRepository.Add(entry);
Now when I find an existing EntryTag, I set it to the Tag property of the Entry. But instead of reusing the EntryTag, the EntryTag gets added (!). I hoped EF would just use the Id to fill in the foreign key? Or am I missing a convention/configuration here?
Thanks