问题
I have been tasked with porting an old app to MVC 3, and want to use EF's code first to replicate its existing database schema. The current code base is littered with hard coded SQL commands, and so the model I come up with has to be "compatible" with what the current system expects. I know I could use EF's Database First to do this, but the existing schema is so simple that I see no reason not to use code first, as I want a solid foundation to build on as we migrate away from our old hard-coded database interactions.
What I need the POCOs to look like:
public class Owner
{
[Key]
public Guid Owner_Id { get; set; }
// Properties
public string ContactName { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
// Navigational properties
public virtual ICollection<Plant> Plants { get; set; }
}
public class Plant
{
[Key]
public Guid Plant_Id { get; set; }
// Properties
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
// Foreign Keys
public Guid Owner_Id { get; set; }
// Navigational properties
public virtual Owner Owner { get; set; }
public virtual License License { get; set; }
}
public class License
{
[Key] public Guid License_Id { get; set; }
// Properties
public int Total { get; set; }
public int Users { get; set; }
public string Key { get; set; }
// Foreign Keys
public Guid Plant_Id { get; set; }
// Navigational properties
public virtual Plant Plant { get; set; }
}
It's giving me this error on attempting to create the context:
"Unable to determine the principal end of an association between the types 'License' and 'Plant'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations."
I realize that Plant should have a nullable FK reference to a License_Id, and that License shouldn't have a FK for Plant_Id. But these are the cards I have been dealt. Is what I'm trying to do possible in EF?
回答1:
public class Plant
{
public Guid PlantID { get; set; }
public virtual License License { get; set; }
}
public class License
{
// No need to have a PlantID foreign key since the foreign key.
public Guid LicenseID { get; set; }
public virtual Plant Plant { get; set; }
}
In fluent-api (in your context class):
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Plant>().HasOptional(p => p.License).WithRequired(l => l.Plant);
The only downgrade is that you actually defined one to zero or one. (which can be handled in code. but still...) For more info about One-to-One relationship please check out Entity Framework Code First One to One Relationship
回答2:
try adding in License
// Foreign Keys
public Guid Plant_Id { get; set; }
// Navigational properties
[ForeignKey("Plant_Id")]
public virtual Plant Plant { get; set; }
to let it know that this is foreign key, same for the other foreign keys.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Plant>()
.HasOptional(e => e.License)
.WithOptionalPrincipal(e => e.Plant);
}
来源:https://stackoverflow.com/questions/7840828/one-to-one-mapping-in-ef-code-first-and-bi-directional-navigation-properties