Entity framework (CTP5, Fluent API). Rename column of navigation property - entity-framework

I have two entites:
public class Address
{
public int Id { get; set; }
public string FirstName { get; set;
public string LastName { get; set; }
}
public partial class Customer
{
public int Id { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public virtual Address BillingAddress { get; set; }
public virtual Address ShippingAddress { get; set; }
}
Below are mapping classes:
public partial class AddressMap : EntityTypeConfiguration<Address>
{
public AddressMap()
{
this.ToTable("Addresses");
this.HasKey(a => a.Id);
}
}
public partial class CustomerMap : EntityTypeConfiguration<Customer>
{
public CustomerMap()
{
this.ToTable("Customer");
this.HasKey(c => c.Id);
this.HasOptional<Address>(c => c.BillingAddress);
this.HasOptional<Address>(c => c.ShippingAddress);
}
}
When database is generated, my 'Customer' table has two columns for 'BillingAddress' and 'ShippingAddress' properties. Their names are 'AddressId' and 'AddressId1'.
Question: how can I rename them to 'BillingAddressId' and 'ShippingAddressId'?

Basically you want to customize the FK column name in an independent association and this code will do this for you:
public CustomerMap()
{
this.ToTable("Customer");
this.HasOptional<Address>(c => c.BillingAddress)
.WithMany()
.IsIndependent().Map(m =>
{
m.MapKey(a => a.Id, "BillingAddressId");
});
this.HasOptional<Address>(c => c.ShippingAddress)
.WithMany()
.IsIndependent().Map(m =>
{
m.MapKey(a => a.Id, "ShippingAddressId");
});
}

Related

EntityTypeConfiguration for base classes with One-To-Many

I am unable to configure EntityFramework migration to create DB structure by the hierarchy provided.
Consider the following:
public class EntityBase
{
public EntityBase()
{
UId = Guid.NewGuid();
CreateTime = DateTime.UtcNow;
}
[Key]
public Guid UId { get; set; }
}
public class Matrix : EntityBase
{
public Guid PassportUId { get; set; }
public virtual Contracts.Entities.Passport Passport { get; set; }
public DeviceBlockType Type { get; set; }
public virtual ICollection<DeviceBlockBase> Blocks { get; set; }
}
public class DeviceBlockBase: EntityBase
{
public string State { get; set; }
public Guid? MatrixUId { get; set; }
public virtual Matrix Matrix { get; set; }
}
public class ArrayBlock: DeviceBlockBase
{
public string LotNumber { get; set; }
public string TransNum { get; set; }
public Guid? LockoutByUId { get; set; }
public virtual User LockoutBy { get; set; }
public DateTime? LockoutFrom { get; set; }
public DateTime? LockoutTill { get; set; }
public Guid? LockoutReasonUId { get; set; }
public virtual LockoutReason LockoutReason { get; set; }
}
public class Container : ArrayBlock
{
public DateTime FillDate { get; set; }
public bool? IsLearned { get; set; }
}
public class Cartridge: ArrayBlock
{
public DateTime LoadDate { get; set; }
public Guid LoaderUid { get; set; }
public User Loader { get; set; }
public bool IsOpen { get; set; }
}
public class Vault: DeviceBlockBase
{
public DateTime FillDate { get; set; }
}
Edited (Configuration class):
public abstract class BaseBlockDeviceConfiguration<T> : EntityTypeConfiguration<T> where T : DeviceBlockBase
{
protected BaseBlockDeviceConfiguration()
{
HasOptional(x => x.MedicationMatrix)
.WithMany()
.HasForeignKey(x => x.MedicationMatrixUId);
}
}
public abstract class BaseArrayBlockConfiguration<T> : BaseBlockDeviceConfiguration<T> where T : ArrayBlock
{
protected BaseArrayBlockConfiguration()
{
HasOptional(x => x.LockoutBy)
.WithMany()
.HasForeignKey(x => x.LockoutByUId)
.WillCascadeOnDelete(false);
HasOptional(x => x.LockoutReason)
.WithMany()
.HasForeignKey(x => x.LockoutReasonUId)
.WillCascadeOnDelete(false);
}
}
public class CartridgeConfiguration : BaseArrayBlockConfiguration<Cartridge>
{
public CartridgeConfiguration()
{
HasOptional(p => p.Loader)
.WithMany()
.HasForeignKey(p => p.LoaderUid)
.WillCascadeOnDelete(false);
}
}
public class ContainerConfiguration : BaseArrayBlockConfiguration<Container>
{
public ContainerConfiguration()
{
}
}
public class VaultConfiguration : BaseBlockDeviceConfiguration<Vault>
{
public VaultConfiguration()
{
}
}
The EntityTypeConfiguration builds the DB in somewhat weird structure:
RenameTable(name: "dbo.Cartridges", newName: "DeviceBlockBases");
AddColumn("dbo.DeviceBlockBases", "FillDate", c => c.DateTime());
AddColumn("dbo.DeviceBlockBases", "IsLearned", c => c.Boolean());
AddColumn("dbo.DeviceBlockBases", "FillDate1", c => c.DateTime());
AddColumn("dbo.DeviceBlockBases", "FillDate2", c => c.DateTime());
AddColumn("dbo.DeviceBlockBases", "Discriminator", c => c.String(nullable: false, maxLength: 128));
DropTable("dbo.Containers");
It looks like EF CodeFirst refuses to generate polymorphism and is going wild.
Any ideas?
Thanks ahead

EF6 Ignoring related data

Scenario
public class Product : Entity, IAggregateRoot
{
public string Name { get; set; }
public string Dimension { get; set; }
public decimal Volume { get; set; }
public bool Featured { get; set; }
public Farm Farm { get; set; }
public int FarmId { get; set; }
/// <summary>
/// Sell Price
/// </summary>
public decimal BidPrice { get; set; }
public int QuantityAvaliable { get; set; }
public ICollection<Image> Images { get; set; }
public string Description { get; set; }
public Category Category { get; set; }
public int CategoryId { get; set; }
public DateTime Created { get; set; }
public DateTime? Modified { get; set; }
}
public class Category : Entity, IAggregateRoot
{
public string Title { get; set; }
public string CategoryImage { get; set; }
public Category Parent { get; set; }
public DateTime Created { get; set; }
public DateTime? Modified { get; set; }
}
Relationship setup
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
HasKey(x => x.Id);
Property(x => x.Created).HasColumnType("DateTime");
Property(x => x.Modified).HasColumnType("DateTime");
Property(x => x.BidPrice).HasColumnType("Decimal");
#region RELATIONSHIP
//BelongsTo
HasRequired(x => x.Farm);
HasRequired(x => x.Category);
HasMany(x => x.Images);
#endregion
}
So I have this two model where I need to bring the data from Product model with Category information
I have checked my database, the data is consistent, the Product record have the FK for the Category record.
but when I try to get Product Data using EF6, the category information doesnt come, I get a null object.
Because of = () =>
{
_product = _repository.Find(p => p.Id == 1, p => p.Category);
};
It should_not_be_bull = () =>
_product.Category.ShouldNotBeNull();
the response from data base is for Category is null. but the record is there.
I had it working properly before. for some random magic reason it just stop working.
THE FIND method
public virtual TEntity Find(Expression<Func<TEntity, bool>> predicate = null, params Expression<Func<TEntity, object>>[] includes)
{
var set = CreateIncludedSet(includes);
return (predicate == null) ?
set.FirstOrDefault() :
set.FirstOrDefault(predicate);
}
the CreateIncludeSet
private IDbSet<TEntity> CreateIncludedSet(IEnumerable<Expression<Func<TEntity, object>>> includes)
{
var set = CreateSet();
if (includes != null)
{
foreach (var include in includes)
{
set.Include(include);
}
}
return set;
}
the CreateSet method
private IDbSet<TEntity> CreateSet()
{
return Context.CreateSet<TEntity>();
}
MY DbContext implementation is here
https://github.com/RobsonKarls/FreedomWebApi/blob/dev/Source/Freedom.Infrastructure.DataAccess/Factories/FreedomDbContext.cs
all project is there too for further analisys
any help is valuable.
Thank you
The problem in your code is in this line in CreateIncludedSet method:
set.Include(include);
Yes, you include the data but you do not change you set. You should change it to something like:
set = set.Include(include);
Your code is a bit unclear, but try something like this....
_product = _repository.Include(p => p.Category).SingleOrDefault(x => x.Id == 1);
also see...
https://stackoverflow.com/a/7348694/6200410

Inserting a dependent entity when inserting a parent with Entity Framework

I am having an issue inserting a record for a dependent entity when inserting the parent. Below is my entity definitions and mappings
EBUser
public partial class EBUser : ModelBase, IUser<long>
{
public string UserName { get; set; }
public string Password { get; set; }
public long AccountId { get; set; }
public EBAccount EbAccount { get; set; }
public string Email { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? LastUpdateDate { get; set; }
public virtual EBUserInfo UserInfo { get; set; }
}
EBUserInfo
public partial class EBUserInfo : ModelBase
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string DisplayName { get; set; }
public virtual EBUser User { get; set; }
}
EBUserMapping
public class EBUserMapping : BaseEntityMapping<EBUser>
{
public EBUserMapping()
{
this.ToTable("Users");
this.Property(u => u.AccountId).HasColumnName("AccountId");
this.Property(u => u.Password).HasColumnName("Password");
this.Property(u => u.UserName).HasColumnName("UserName");
this.Property(u => u.Email).HasColumnName("Email");
this.Property(u => u.CreatedDate).HasColumnName("CreatedDate");
this.Property(u => u.LastUpdateDate).HasColumnName("LastUpdateDate").IsOptional();
//this.HasRequired(u => u.UserInfo).WithRequiredDependent(u => u.User);
this.HasRequired(t => t.EbAccount)
.WithMany(t => t.Users)
.HasForeignKey(d => d.AccountId);
}
}
EBUserInfoMapping
public class EBUserInfoMapping :BaseEntityMapping<EBUserInfo>
{
public EBUserInfoMapping()
{
this.ToTable("UserInfo");
this.Property(u => u.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(u => u.Email).HasColumnName("Email");
this.Property(u => u.FirstName).HasColumnName("FirstName");
this.Property(u => u.LastName).HasColumnName("LastName");
this.Property(u => u.DisplayName).HasColumnName("DisplayName");
// Relationships
this.HasRequired(t => t.User).//WithRequiredDependent(t => t.UserInfo);
WithOptional(t => t.UserInfo);
}
}
In the database schema, all tables have an ID column but in the EBUserInfor class the Id column is both the primary and foreign key to the EBUsers table.
The BaseEntityuMapping maps the Id column and set the DatabaseGenerationOptions to identity but in the EBUserinfoMapping class I overwrite that with a DatabaseGenerationOption of None.
When I insert a new EBUser record using Entity Framework, the user record is created but no userInfo record is created
Please help
Thanks
Map user to userInfo as
EBuser user= new EBuser();
// fill here user
EBuserInfo info = new EBuserInfo();
Info.userInfo= user;
// fill here rest info
db.add(info);
db.saveChanges();

Entity Framework Many To Many returns null

I have Many To Many relationship defined and when I try to query for the records that should be in the map I get null.
public class Record
{
public int RecordId { get; set; }
public DateTime DateRecordCreated { get; set; }
public ICollection<Street> Streets { get; set; }
public ICollection<Street> CrossStreets { get; set; }
}
public class RecordMap : EntityTypeConfiguration<Record>
{
public RecordMap()
{
// Primary Key
this.HasKey(t => t.RecordId);
this.HasMany(r => r.Streets)
.WithMany(c => c.Records)
.Map(sl =>
{
sl.ToTable("StreetRecordMap", "dbo");
sl.MapLeftKey("RecordId");
sl.MapRightKey("StreetId");
});
this.HasMany(r => r.CrossStreets)
.WithMany(c => c.AnotherRecord)
.Map(sl =>
{
sl.ToTable("AnotherStreetRecordMap", "dbo");
sl.MapLeftKey("RecordId");
sl.MapRightKey("StreetId");
});
this.Property(t => t.DateRecordCreated).IsRequired();
}
}
public class House : Record
{
public string HouseNumber { get; set; }
public string StreeName { get; set; }
public int ZipCode { get; set; }
}
public class Street
{
public int StreetId { get; set; }
public string StreetName { get; set; }
public ICollection<Record> Records { get; set; }
public ICollection<Record> AnotherRecord { get; set; }
}
Now when I run the following query below I get houses.CrossStreets as null, I tried adding enabling lazy loading and had the same out come.
public static void GetRecords()
{
using (var context = new SandboxContext())
{
var entities = context.Houses.Include(r => r.CrossStreets);
var houses = entities.ToList();
}
}

Entity Framework Mapping Foreign Key with Collections and TPH Inhehritance

I Try to map this simple model with TPH inheritance :
public abstract class Master {
public long Id {
get;
set;
}
public virtual ICollection<Detail> Details {
get;
set;
}
}
public class MasterA : Master {
public string FieldA {
get;
set;
}
}
public class MasterB : Master {
public string FieldB {
get;
set;
}
}
public abstract class Detail {
public long Id {
get;
set;
}
public long MasterId {
get;
set;
}
public Master Master {
get;
set;
}
public String CommonDetailInfo {
get;
set;
}
}
public class DetailA : Detail {
public MasterA MasterA {
get;
set;
}
public string SpecificA {
get;
set;
}
}
public class DetailB : Detail {
public MasterB MasterB {
get;
set;
}
public string SpecificB {
get;
set;
}
}
Mapping is done with fluent Notation Like this :
modelBuilder.Entity<Master>().ToTable("TestMaster");
modelBuilder.Entity<Master>().Property(m => m.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Master>().HasKey(m => m.Id);
modelBuilder.Entity<Master>().Map<MasterA>(m => m.Requires("MasterType").HasValue("A"));
modelBuilder.Entity<Master>().Map<MasterB>(m => m.Requires("MasterType").HasValue("B"));
modelBuilder.Entity<Detail>().ToTable("TestDetail");
modelBuilder.Entity<Detail>().Property(d => d.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Detail>().HasKey(d => d.Id);
modelBuilder.Entity<Detail>().Map<DetailA>(m => m.Requires("DetailType").HasValue("A"));
modelBuilder.Entity<Detail>().Map<DetailB>(m => m.Requires("DetailType").HasValue("B"));
modelBuilder.Entity<Master>()
.HasMany(m => m.Details)
.WithRequired(d => d.Master)
.HasForeignKey(f => f.MasterId)
.WillCascadeOnDelete();
If I let EF create my database, two fields are added in TestDetail table :
MasterA_Id
MasterB_Id
But these two fields are always Null and redundant because MasterId field on base Dteail Class do the same job ?
If I remove these fields from database and try to get Details on a master record like this :
foreach (var detail in master.Details) {...}
An Exception is raised : Invalid ColumnName MasterA_Id, MasterB_Id when I access "Details" property.
What I'm doing wrong ?
How can I map this model in TPH mode without having these two fields in database ?
Thanks for your help.