I have two classes. A Company has a County set against it:
public class Company
{
public int Id { get; set; }
public string CompanyName { get; set; }
public Country HomeCountry { get; set; }
}
public class Country
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
I am trying to map to an existing database where the Company table contains the foreign key of the Country record. So I presumably need to tell code first the name of the foreign key column.
Below is the complete code example. It's currently failing with different exceptions based on different things that I try. There's seems to be a lack of cohesive documentation on this as yet.
So using Code First Fluent API how do I define the name of the foreign key column?
Test app:
Create database as follows: CREATE DATABASE CodeFirst; GO
Use CodeFirst
create table Companies
(
Id int identity(1,1) not null,
HomeCountryId int not null,
Name varchar(20) not null,
constraint PK_Companies primary key clustered (Id)
)
create table Countries
(
Id int identity(1,1) not null
, Code varchar(4) not null
, Name varchar(20) not null
, constraint PK_Countries primary key clustered (Id)
)
alter table Companies
add
constraint FK_Company_HomeCountry foreign key (HomeCountryId)
references Countries (Id) on delete no action
Now run the following C# app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Data;
namespace CodeFirstExistingDatabase
{
class Program
{
private const string ConnectionString = @"Server=.\sql2005;Database=CodeFirst;integrated security=SSPI;";
static void Main(string[] args)
{
// Firstly, add a country record, this works fine.
Country country = new Country();
country.Code = "UK";
country.Name = "United Kingdom";
MyContext myContext = new MyContext(ConnectionString);
myContext.Countries.Add(country);
myContext.Entry(country).State = EntityState.Added;
myContext.SaveChanges();
Console.WriteLine("Saved Country");
// Now insert a Company record
Company company = new Company();
company.CompanyName = "AccessUK";
company.HomeCountry = myContext.Countries.First(e => e.Code == "UK");
myContext.Companies.Add(company);
myContext.Entry(company).State = EntityState.Added;
myContext.Entry(country).State = EntityState.Unchanged;
myContext.SaveChanges();
Console.WriteLine("Saved Company"); // If I can get here I'd he happy!
}
}
public class MyContext
: DbContext
{
public DbSet<Company> Companies { get; set; }
public DbSet<Country> Countries { get; set; }
public MyContext(string connectionString)
: base(connectionString)
{
Database.SetInitializer<MyContext>(null);
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CountryConfiguration());
modelBuilder.Configurations.Add(new CompanyConfiguration());
base.OnModelCreating(modelBuilder);
}
}
public class CompanyConfiguration
: EntityTypeConfiguration<Company>
{
public CompanyConfiguration()
: base()
{
HasKey(p => p.Id);
Property(p => p.Id)
.HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
Property(p => p.CompanyName)
.HasColumnName("Name")
.IsRequired();
ToTable("Companies");
}
}
public class CountryConfiguration
: EntityTypeConfiguration<Country>
{
/// <summary>
/// Initializes a new instance of the <see cref="CountryConfiguration"/> class.
/// </summary>
public CountryConfiguration()
: base()
{
HasKey(p => p.Id);
Property(p => p.Id)
.HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
Property(p => p.Code)
.HasColumnName("Code")
.IsRequired();
Property(p => p.Name)
.HasColumnName("Name")
.IsRequired();
ToTable("Countries");
}
}
public class Company
{
public int Id { get; set; }
public string CompanyName { get; set; }
public Country HomeCountry { get; set; }
}
public class Country
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
}
The above fails with the following when saving the country: Invalid column name 'HomeCountry_Id
Any help would be very much appreciated!!
Thanks, Paul.
To use code-first for an existing database, right click on your project in Visual Studio -> Add -> New Item.. Select ADO.NET Entity Data Model in the Add New Item dialog box and specify the model name (this will be a context class name) and click on Add.
There is no way to convert your code-first classes into database-first classes. Creating the model from the database will create a whole new set of classes, regardless of the presence of your code-first classes. However, you might not want to delete your code-first classes right away.
The main difference between Code First approach and Database First approach is that the Code First enables you to write entity classes and its properties first without creating the database design first.
public CompanyConfiguration()
{
//...
HasRequired(x => x.HomeCountry).WithMany()
.Map(x => x.MapKey("HomeCountryId"));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With