I have been struggling for a while now to convert a fairly large EntityFramework database created in model first to codefirst. I have a problem that I cant seem to resolve. I am getting an Object reference not set to an instance of an object with the following procedures on the call stack.
ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure
ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities
to simplify the post I have created a test project that boils the problem down to its simplest form.
I have 3 classes
a which has an has an optional b and an optional c
b which has a collection of a's, and a colleciton of c's
c which has an optional b and a collection of a's
public class a
{
public int Id { get; set; }
[Required]
public string name { get; set; }
public virtual b b { get; set; }
[ForeignKey("b")]
public int? b_Id { get; set; }
public virtual c c { get; set; }
[ForeignKey("c")]
public int? c_Id { get; set; }
}
public class b
{
public int Id { get; set; }
public string name { get; set; }
public virtual ICollection<a> a_s { get; set; }
public virtual ICollection<c> c_s { get; set; }
}
public class c
{
public int Id { get; set; }
public virtual b b { get; set; }
[ForeignKey("b")]
public int? b_Id { get; set; }
public virtual ICollection<a> a_s { get; set; }
}
public class MyContext : DbContext
{
public DbSet<a> a { get; set; }
public DbSet<b> b { get; set; }
public DbSet<c> c { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<a>()
.HasOptional(m => m.b)
.WithMany(m => m.a_s);
modelBuilder.Entity<b>()
.HasMany(m => m.c_s)
.WithRequired(m => m.b);
modelBuilder.Entity<c>()
.HasMany(m => m.a_s)
.WithOptional(m => m.c);
base.OnModelCreating(modelBuilder);
}
}
when I execute the code var a = from o in db.a select o, I get the error described above. There is absolutely no information on what is hapenning, so I really dont know where to turn. Can anyone help me solve this problem, as I really want to move away from Model First.
namespace MvcApplication2.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var db = new MyContext();
var a = from o in db.a select o;
return View();
}
}
}
The mixup of fluent configuration and data annotation caused this problem. EF team should have handled this exception and given a meaningful error message.
Remove data annotations and use fluent configuration as follows
public class a
{
public int Id { get; set; }
[Required]
public string name { get; set; }
public virtual b b { get; set; }
public int? b_Id { get; set; }
public virtual c c { get; set; }
public int? c_Id { get; set; }
}
public class b
{
public int Id { get; set; }
public string name { get; set; }
public virtual ICollection<a> a_s { get; set; }
public virtual ICollection<c> c_s { get; set; }
}
public class c
{
public int Id { get; set; }
public virtual b b { get; set; }
public int? b_Id { get; set; }
public virtual ICollection<a> a_s { get; set; }
}
public class NreContext : DbContext
{
public DbSet<a> a { get; set; }
public DbSet<b> b { get; set; }
public DbSet<c> c { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<a>()
.HasOptional(m => m.b)
.WithMany(m => m.a_s)
.HasForeignKey(m => m.b_Id);
modelBuilder.Entity<a>()
.HasOptional(m => m.c)
.WithMany(m => m.a_s)
.HasForeignKey(m => m.c_Id);
modelBuilder.Entity<c>()
.HasOptional(m => m.b)
.WithMany(m => m.c_s)
.HasForeignKey(m => m.b_Id);
base.OnModelCreating(modelBuilder);
}
}
Try putting 'a' into local memory:
var a = from o in db.a.ToList() select o;
Related
How to add multiple many-to-many relationships between Entities in EF Core 5.x, with join entity (linking tables)?
What I what is two many-to-many relationships between Card and Game. One relationship is not a problem but two (or more) I'm not able to configure it correctly.
What's working at the moment for me is that I created two different classes DeckGameCard and TableGameCard (join entity), which forces EF to create two tables. The classes are the same except for the name. Is it possible to have only one class (join entity) and two linking tables in the database?
What I want is this:
public class Game
{
[Key]
public int Id { get; set; }
public ICollection<GameCard> Deck { get; set; }
public ICollection<GameCard> OnTable { get; set; }
...
But at the moment this (the code below) is my solution (not optimal, because of code duplication in DeckGameCard and TableGameCard).
public class DeckGameCard
{
public int GameId { get; set; }
public Game Game { get; set; }
public int Order { get; set; }
public int CardId { get; set; }
public Card Card { get; set; }
}
public class TableGameCard
{
public int GameId { get; set; }
public Game Game { get; set; }
public int Order { get; set; }
public int CardId { get; set; }
public Card Card { get; set; }
}
public class Game
{
[Key]
public int Id { get; set; }
public ICollection<DeckGameCard> Deck { get; set; }
public ICollection<TableGameCard> OnTable { get; set; }
[Required]
public int CardIndex { get; set; }
[Required]
public int PlayerId { get; set; }
[Required]
public Player Player { get; set; }
}
public class Card : IEntity
{
[Key]
public int Id { get; set; }
[Required]
public Shape Shape { get; set; }
[Required]
public Fill Fill { get; set; }
[Required]
public Color Color { get; set; }
[Required]
public int NrOfShapes { get; set; }
public ICollection<DeckGameCard> Deck { get; set; }
public ICollection<TableGameCard> OnTable { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<DeckGameCard>()
.HasKey(x => new {x.GameId, x.CardId});
modelBuilder.Entity<DeckGameCard>()
.HasOne(gc => gc.Card)
.WithMany(b => b.Deck)
.HasForeignKey(gc => gc.CardId);
modelBuilder.Entity<DeckGameCard>()
.HasOne(gc => gc.Game)
.WithMany(g => g.Deck)
.HasForeignKey(gc => gc.GameId);
modelBuilder.Entity<TableGameCard>()
.HasKey(x => new {x.GameId, x.CardId});
modelBuilder.Entity<TableGameCard>()
.HasOne(gc => gc.Card)
.WithMany(b => b.OnTable)
.HasForeignKey(bc => bc.CardId);
modelBuilder.Entity<TableGameCard>()
.HasOne(gc => gc.Game)
.WithMany(g => g.OnTable)
.HasForeignKey(gc => gc.GameId);
}
Yes, it's possible by using the EF Core 5.0 introduced Shared-type entity types, but not sure it's worth since the type of an object no more uniquely identifies the entity type, so most if not all generic and non generic entity services (methods) of DbContext won't work, and you have to use the corresponding DbSet<T> methods, obtaining it using the Set<T>(name) overload. And there is no equivalent of Entry method, so you might have problems with change tracking in disconnected scenarios.
With that being said, here is how it can be done at model level.
Given the model similar to:
public class Game
{
public int Id { get; set; }
// ...
public ICollection<GameCard> Deck { get; set; }
public ICollection<GameCard> OnTable { get; set; }
}
public class Card
{
public int Id { get; set; }
// ...
public ICollection<GameCard> Deck { get; set; }
public ICollection<GameCard> OnTable { get; set; }
}
public class GameCard
{
public int GameId { get; set; }
public Game Game { get; set; }
public int Order { get; set; }
public int CardId { get; set; }
public Card Card { get; set; }
}
it can be configured as follows:
modelBuilder.SharedTypeEntity<GameCard>("DeckGameCard", builder =>
{
builder.ToTable("DeckGameCard");
builder.HasKey(e => new { e.GameId, e.CardId });
builder.HasOne(e => e.Card).WithMany(e => e.Deck);
builder.HasOne(e => e.Game).WithMany(e => e.Deck);
});
modelBuilder.SharedTypeEntity<GameCard>("TableGameCard", builder =>
{
builder.ToTable("TableGameCard");
builder.HasKey(e => new { e.GameId, e.CardId });
builder.HasOne(e => e.Card).WithMany(e => e.OnTable);
builder.HasOne(e => e.Game).WithMany(e => e.OnTable);
});
or since the only difference is the entity (table) name and the corresponding collection navigation properties, the configuration can be factored out to a method similar to
static void GameCardEntity(
ModelBuilder modelBuilder, string name,
Expression<Func<Card, IEnumerable<GameCard>>> cardCollection,
Expression<Func<Game, IEnumerable<GameCard>>> gameCollection,
string tableName = null
)
{
var builder = modelBuilder.SharedTypeEntity<GameCard>(name);
builder.ToTable(tableName ?? name);
builder.HasKey(e => new { e.GameId, e.CardId });
builder.HasOne(e => e.Card).WithMany(cardCollection);
builder.HasOne(e => e.Game).WithMany(gameCollection);
}
so the configuration becomes simply
GameCardEntity(modelBuilder, "DeckGameCard", c => c.Deck, g => g.Deck);
GameCardEntity(modelBuilder, "TableGameCard", c => c.OnTable, g => g.OnTable);
This should answer your concrete question. But again, make sure you understand the potential problems with it. And compare to "straight forward" solution achieving the same reusability with base class (not entity) without the above drawbacks, e.g.
public class Game
{
public int Id { get; set; }
// ...
public ICollection<DeskGameCard> Deck { get; set; }
public ICollection<TableGameCard> OnTable { get; set; }
}
public class Card
{
public int Id { get; set; }
// ...
public ICollection<DeskGameCard> Deck { get; set; }
public ICollection<TableGameCard> OnTable { get; set; }
}
public abstract class GameCard
{
public int GameId { get; set; }
public Game Game { get; set; }
public int Order { get; set; }
public int CardId { get; set; }
public Card Card { get; set; }
}
public class DeskGameCard : GameCard { }
public class TableGameCard : GameCard { }
with only fluent configuration needed for composite PK
modelBuilder.Entity<DeskGameCard>().HasKey(e => new { e.GameId, e.CardId });
modelBuilder.Entity<TableGameCard>().HasKey(e => new { e.GameId, e.CardId });
I'm trying to make a simple app to try Entity Framework Core, but i a have problem with setting up relations between entities. My entities:
public class Card
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Adress { get; set; }
public DateTime DoB { get; set; }
public DateTime DoS { get; set; }
public User Portal { get; set; }
public List<Reservation> Res { get; set; }
}
public class Doctor
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public TimeSpan Start_Working { get; set; }
public TimeSpan End_Working { get; set; }
public List<Reservation> Reservations { get; set; }
public int SpecID { get; set; }
public Spec Spec { get; set; }
}
public class Reservation
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime DoR { get; set; }
public string Info { get; set; }
public int CardID { get; set; }
public Card Card_Nav_R { get; set; }
public int DoctorID { get; set; }
public Doctor Doctor { get; set; }
}
public class Spec
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public List<Doctor> Doctors { get; set; }
}
public class User
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public int CardID { get; set; }
public Card Card { get; set; }
}
And a configuration class where i tried to set up relations:
class ApplicationContext:DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Card> Cards { get; set; }
public DbSet<Reservation> Reservations { get; set; }
public DbSet<Doctor> Doctors { get; set; }
public DbSet<Spec> Specs { get; set; }
public ApplicationContext()
{
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder ModelBuilder)
{
ModelBuilder.Entity<User>().HasKey(u => u.Id);
ModelBuilder.Entity<Card>().HasKey(c => c.Id);
ModelBuilder.Entity<Doctor>().HasKey(d => d.Id);
ModelBuilder.Entity<Spec>().HasKey(s => s.Id);
ModelBuilder.Entity<Reservation>().HasKey(r => r.Id);
ModelBuilder.Entity<User>().Property(u => u.Email).IsRequired();
ModelBuilder.Entity<User>().Property(u => u.Password).IsRequired();
ModelBuilder.Entity<Card>().Property(c => c.Name).IsRequired();
ModelBuilder.Entity<Card>().Property(c => c.Surname).IsRequired();
ModelBuilder.Entity<Card>().Property(c => c.DoB).IsRequired();
ModelBuilder.Entity<Card>().Property(c => c.Adress).IsRequired();
ModelBuilder.Entity<Doctor>().Property(d => d.Name).IsRequired();
ModelBuilder.Entity<Doctor>().Property(d => d.Surname).IsRequired();
ModelBuilder.Entity<Doctor>().Property(d => d.Spec).IsRequired();
ModelBuilder.Entity<Doctor>().Property(d => d.Email).IsRequired();
ModelBuilder.Entity<Doctor>().Property(d => d.Start_Working).IsRequired();
ModelBuilder.Entity<Doctor>().Property(d => d.End_Working).IsRequired();
ModelBuilder.Entity<Reservation>().Property(r => r.Info).IsRequired();
ModelBuilder.Entity<Reservation>().Property(r => r.Card_Nav_R).IsRequired();
ModelBuilder.Entity<Reservation>().Property(r => r.Doctor).IsRequired();
ModelBuilder.Entity<Reservation>().Property(r => r.DoR).IsRequired();
ModelBuilder.Entity<Spec>().Property(s => s.Name).IsRequired();
ModelBuilder.Entity<Doctor>().HasOne<Spec>(d=>d.Spec).WithMany(s => s.Doctors).HasForeignKey(d => d.SpecID);
ModelBuilder.Entity<User>().HasOne<Card>(u => u.Card).WithOne(c => c.Portal).HasForeignKey<User>(u => u.CardID);
ModelBuilder.Entity<Reservation>().HasOne<Card>(r => r.Card_Nav_R).WithMany(c => c.Res).HasForeignKey(r => r.CardID);
ModelBuilder.Entity<Reservation>().HasOne<Doctor>(r => r.Doctor).WithMany(d => d.Reservations).HasForeignKey(r => r.DoctorID);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=Simple_Try;Trusted_Connection=True;");
}
}
So, when i tried to add migration or add something to database i saw this error:
System.InvalidOperationException: 'The property or navigation 'Spec' cannot be added to the entity type 'Doctor' because a property or navigation with the same name already exists on entity type 'Doctor'.'
I really don't know how to fix this, i tried to use annotations instead of Fluent API, but had the same result.
The cause of the exception is the following line:
ModelBuilder.Entity<Doctor>().Property(d => d.Spec).IsRequired();
because Doctor.Spec is a navigation property
public class Doctor
{
// ...
public Spec Spec { get; set; }
}
and navigation properties cannot be configured via Property fluent API.
So simply remove that line. Whether reference navigation property is required or optional is controlled via relationship configuration. In this case
ModelBuilder.Entity<Doctor>()
.HasOne(d => d.Spec)
.WithMany(s => s.Doctors)
.HasForeignKey(d => d.SpecID)
.IsRequired(); // <--
although the IsRequired is automatically derived from the FK property type - since SpecID is non nullable, then the relationship is required.
For more info, see Required and Optional Properties and Required and Optional Relationships documentation topics.
I have these Classes :
public class A
{
public A()
{
nameA = string.Empty;
ListB = new List<B>();
}
public string nameA { get; set; }
public List<B> ListB { get; set; }
}
public class B
{
public C cObject { get; set; }
public string nameB { get; set; }
}
public class C
{
public string nameC { get; set; }
}
I'm using Microsoft.EntityFrameworkCore to work with the Database for these models, I'm able to generate the DB and the right tables, but I'm missing two things :
The relationship between (A and B), and( B and C).
and the Ability the Add and delete objects on cascade (for example
in my case when deleting an Object A delete the corresponding List
of B objects with it).
Here is the Code in my Context File :
public class Context : DbContext
{
#region Tables
public DbSet<A> As{ get; set; }
public DbSet<B> Bs { get; set; }
public DbSet<C> Cs { get; set; }
#endregion
public Context(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//primary key's
modelBuilder.Entity<A>().HasKey(x => x.nameA);
modelBuilder.Entity<B>().HasKey(x => x.nameB);
modelBuilder.Entity<C>().HasKey(x => x.nameC);
//foreign key's
modelBuilder.Entity<A>().HasMany<B>(app => app.ListB);
modelBuilder.Entity<B>().HasOne<C>(app => app.cObject);
base.OnModelCreating(modelBuilder);
}
}
You can use the below code for your requirement. You have to use A table's PK as the foreign key in B and C tables PK as the foreign key on B. If you want the DeleteBehavior.Cascade then you have to use Required. Or you can do this using Fluent API.
public class A
{
public A()
{
nameA = string.Empty;
ListB = new List<B>();
}
public string nameA { get; set; }
public List<B> B{ get; set; }
}
public class B
{
public int CForeignKey { get; set; }
[ForeignKey("CForeignKey")]
public C C { get; set; }
public string nameB { get; set; }
[Required]
public int AForeignKey { get; set; }
[ForeignKey("AForeignKey")]
public A A {get; set;}
}
public class C
{
public string nameC { get; set; }
}
Fluent API:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<B>()
.HasOne(p => p.A)
.WithMany(b => b.B)
.OnDelete(DeleteBehavior.Cascade);
}
I'm about to create a Generic Entity and EntityTypeConfiguration for my entities. here are my classes:
IEntity
public interface IEntity<T>
{
T Id { get; set; }
}
public interface IAuditableEntity<T>
{
DateTime CreatedAt { get; set; }
Membership.User CreatedBy { get; set; }
int? CreatedById { get; set; }
DateTime? DeletedAt { get; set; }
Membership.User DeletedBy { get; set; }
int? DeletedById { get; set; }
T RevisionParentId { get; set; }
bool isLastVersion { get; set; }
}
Entity.cs
public abstract class BaseEntity
{
}
public abstract class Entity<T> : BaseEntity, IEntity<T>
{
public virtual T Id { get; set; }
}
public abstract class AuditableEntity<T> : Entity<T>, IAuditableEntity<T>
{
public DateTime CreatedAt { get; set; }
public virtual Membership.User CreatedBy { get; set; }
public int? CreatedById { get; set; }
public DateTime? DeletedAt { get; set; }
public virtual Membership.User DeletedBy { get; set; }
public int? DeletedById { get; set; }
public T RevisionParentId { get; set; }
public bool isLastVersion { get; set; }
}
The problem is when I try to define a generic EntityTypeConfiguration of AuditableEntity, because :
public class AuditableEntityConfig<T> : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<T> where T : AuditableEntity<int>
{
public AuditableEntityConfig()
{
HasOptional(x => x.CreatedBy).WithMany().HasForeignKey(x => x.CreatedById);
HasOptional(x => x.DeletedBy).WithMany().HasForeignKey(x => x.DeletedById);
Property(x => x.DeletedAt).IsOptional();
Property(x => x.RevisionParentId).IsOptional();
}
}
public class User : AuditableEntity<long>
{
}
You see I had to AuditableEntity<int> which is wrong and I have no idea what to replace to get it work.
AuditableEntity<int> should be something like AuditableEntity<T> and T can be string, int, guid, long, ...
UPDATE
as suggested by Mike answer, I made changes and updated my question:
public class User : AuditableEntity<int>
{
[Index("IX_uniqueUsername", IsUnique = true)]
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public bool Active { get; set; }
public virtual List<Role> Roles { get; set; }
public virtual List<UserGroup> Groups { get; set; }
public virtual UserProfile Profile { get; set; }
public bool isSuperAdmin { get; set; }
}
public class UserConfig : AuditableEntityConfig<User, int>
{
public UserConfig()
{
ToTable("Account_Users");
Property(x => x.Username).HasMaxLength(200).IsRequired();
Property(x => x.Password).HasMaxLength(200).IsRequired();
Property(x => x.Email).HasMaxLength(200);
HasMany(x => x.Roles).WithMany(x => x.Users).Map(x =>
{
x.ToTable("Account_UserRoles");
x.MapLeftKey("UserId");
x.MapRightKey("RoleId");
});
HasMany(x => x.Groups).WithMany(x => x.Users).Map(x =>
{
x.ToTable("Account_UserGroups");
x.MapLeftKey("UserId");
x.MapRightKey("GroupId");
});
}
}
I get this error now for the RevisionParentId property:
The type 'TK' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Data.Entity.ModelConfiguration.Configuration.StructuralTypeConfiguration<TStructuralType>.Property<T>(System.Linq.Expressions.Expression<System.Func<TStructuralType,T>>)
in this line:
Property(x => x.RevisionParentId).IsOptional();
where T : AuditableEntity<T> will cause recursive type checking. Please try
UPDATED
public class AuditableEntityConfig<T, TK> : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<T>
where T : AuditableEntity<TK> where TK : struct { }
I have my main class:
Person
and some Additional classes:
AddressInfo and DocumentInfo.
How do I configure my relationship so it will work like Person with 2 addresses and 3 documents?
It's not arrays. It's named links.
Looks like:
public class Person
{
public int Id {get;set;}
public virtual AddressInfo RegistrationAddress {get;set;}
public virtual AddressInfo ResidenceAddress {get;set;}
}
public class AdressInfo
{
public int Id {get;set;}
public virtual Person Person {get;set;}
}
Same with DocumentInfo.
It can be not even close to right solution.
Try this. It work for me. I did not do the attribute but the code first api works better for me
namespace OneToOne
{
class Program
{
static void Main(string[] args)
{
using (var db = new MyContext())
{
var person = new Person();
db.Persons.Add(person);
db.SaveChanges();
person = db.Persons.Include("RegistrationAddress").Include("ResidenceAddress").FirstOrDefault();
var address = new AdressInfo { Person = person };
person.RegistrationAddress = address;
person.ResidenceAddress = address;
db.Persons.Attach(person);
db.SaveChanges();
}
}
}
public class MyContext : DbContext
{
public DbSet Persons { get; set; }
public DbSet AdressInfos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new AdressInfoConfig());
modelBuilder.Configurations.Add(new PersonConfig());
}
}
public class PersonConfig : EntityTypeConfiguration
{
public PersonConfig()
{
this.ToTable("Persons");
this.HasKey(x => x.Id).Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class Person
{
public int Id { get; set; }
public virtual AdressInfo RegistrationAddress { get; set; }
public virtual AdressInfo ResidenceAddress { get; set; }
}
public class AdressInfo
{
public int Id { get; set; }
public virtual Person Person { get; set; }
}
public class AdressInfoConfig : EntityTypeConfiguration
{
public AdressInfoConfig()
{
this.ToTable("AdressInfos");
this.HasKey(x => x.Id).Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.RegistrationAddress).WillCascadeOnDelete(false);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.ResidenceAddress).WillCascadeOnDelete(false);
}
}
}
Tried Your solution.
Thats my models:
`
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public string IdentificationNumber { get; set; }
public string HomePhone { get; set; }
public string MobilePhone { get; set; }
public string Email { get; set; }
public bool DeadHead { get; set; }
public virtual PassportInfo Passport { get; set; }
public virtual PassportInfo DriverLicense { get; set; }
public virtual PassportInfo PensionCertificate { get; set; }
public virtual AddressInfo ResidenseAddress { get; set; }
public virtual AddressInfo RegistrationAddress { get; set; }
}
public class PassportInfo
{
public int Id { get; set; }
public string Series { get; set; }
public int Number { get; set; }
public string IssuedBy { get; set; }
public DateTime IssueDate { get; set; }
public virtual Person Person { get; set; }
}
public class AddressInfo
{
public int Id { get; set; }
public string Index { get; set; }
public string Region { get; set; }
public string District { get; set; }
public string Street { get; set; }
public string Locality { get; set; }
public int House { get; set; }
public int Apartment { get; set; }
public int? StreetTypeId { get; set; }
public StreetType StreetType { get; set; }
public int? LocalityTypeId { get; set; }
public LocalityType LocalityType { get; set; }
public virtual Person Person { get; set; }
}
`
And thats my context config:
public class InsuranceContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<AddressInfo> AddressInfos { get; set; }
public DbSet<PassportInfo> PassportInfos { get; set; }
public DbSet<LocalityType> LocalityTypes { get; set; }
public DbSet<StreetType> StreetTypes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new AddressInfoConfig());
modelBuilder.Configurations.Add(new PersonConfig());
modelBuilder.Configurations.Add(new PassportInfoConfig());
}
}
public class PersonConfig : EntityTypeConfiguration<Person>
{
public PersonConfig()
{
this.ToTable("People");
this.HasKey(x => x.Id)
.Property(x => x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class AddressInfoConfig : EntityTypeConfiguration<AddressInfo>
{
public AddressInfoConfig()
{
this.ToTable("AddressInfos");
this.HasKey(x => x.Id).Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.RegistrationAddress).WillCascadeOnDelete(false);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.ResidenseAddress).WillCascadeOnDelete(false);
}
}
public class PassportInfoConfig : EntityTypeConfiguration<PassportInfo>
{
public PassportInfoConfig()
{
this.ToTable("PassportInfos");
this.HasKey(x => x.Id).Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.Passport).WillCascadeOnDelete(false);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.DriverLicense).WillCascadeOnDelete(false);
this.HasOptional(x => x.Person).WithOptionalDependent(x => x.PensionCertificate).WillCascadeOnDelete(false);
}
}
Btw it throws exception "Either the parameter #objname is ambiguous or the claimed #objtype (COLUMN) is wrong." when i try to use context or update a base with migration.