Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

1852 lines
68 KiB
C#

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace FunctionalTests
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Edm;
using System.Linq;
using System.Transactions;
using FunctionalTests.Model;
using Xunit;
public class InheritanceScenarioTests : TestBase
{
[Fact]
public void Orphaned_configured_table_should_throw()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<BaseDependent_165027>().HasKey(
e => new
{
e.Key1,
e.Key2,
});
modelBuilder.Entity<Dependent_165027>()
.Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("Dependent");
});
modelBuilder.Entity<BaseDependent_165027>()
.Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("BaseDependent");
});
Assert.Throws<InvalidOperationException>(
() => BuildMapping(modelBuilder))
.ValidateMessage("OrphanedConfiguredTableDetected", "BaseDependent");
}
[Fact]
public void Orphaned_unconfigured_table_should_be_removed()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<BaseDependent_165027>().HasKey(
e => new
{
e.Key1,
e.Key2,
});
modelBuilder.Entity<Dependent_165027>()
.Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("Dependent");
});
modelBuilder.Entity<BaseDependent_165027>()
.Map(mapping => mapping.MapInheritedProperties());
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal(1, databaseMapping.Database.EntityTypes.Count());
}
[Fact]
public void Should_be_able_configure_base_properties_via_derived_type()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Base_195898>().ToTable("Base");
modelBuilder.Entity<Base_195898>().Property(b => b.Id).HasColumnName("base_c");
modelBuilder.Entity<Base_195898>().Property(b => b.Complex.Foo).HasColumnName("base_foo");
modelBuilder.Entity<Derived_195898>().ToTable("Derived");
modelBuilder.Entity<Derived_195898>().Property(d => d.Id).HasColumnName("derived_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("derived_foo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
modelBuilder.Entity<Base_195898>().Property(b => b.Id).HasColumnName("base_c");
modelBuilder.Entity<Base_195898>().Property(b => b.Complex.Foo).HasColumnName("base_foo");
modelBuilder.Entity<Derived_195898>().Property(d => d.Id).HasColumnName("derived_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("derived_foo");
}
[Fact]
public void Should_be_able_configure_base_properties_via_derived_type_reverse()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Derived_195898>().ToTable("Derived");
modelBuilder.Entity<Derived_195898>().Property(d => d.Id).HasColumnName("derived_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("derived_foo");
modelBuilder.Entity<Base_195898>().ToTable("Base");
modelBuilder.Entity<Base_195898>().Property(b => b.Id).HasColumnName("base_c");
modelBuilder.Entity<Base_195898>().Property(b => b.Complex.Foo).HasColumnName("base_foo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
modelBuilder.Entity<Base_195898>().Property(b => b.Id).HasColumnName("base_c");
modelBuilder.Entity<Base_195898>().Property(b => b.Complex.Foo).HasColumnName("base_foo");
modelBuilder.Entity<Derived_195898>().Property(d => d.Id).HasColumnName("derived_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("derived_foo");
}
[Fact]
public void Should_be_able_configure_derived_property_and_base_property_is_not_configured()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Base_195898>().ToTable("Base");
modelBuilder.Entity<Derived_195898>().ToTable("Derived");
modelBuilder.Entity<Derived_195898>().Property(d => d.Id).HasColumnName("derived_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("derived_foo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
modelBuilder.Entity<Base_195898>().Property(b => b.Id).HasColumnName("Id");
modelBuilder.Entity<Base_195898>().Property(b => b.Complex.Foo).HasColumnName("Foo");
modelBuilder.Entity<Derived_195898>().Property(b => b.Id).HasColumnName("derived_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("derived_foo");
}
[Fact]
public void Should_be_able_configure_base_property_and_derived_property_inherits_configuration()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Base_195898>().ToTable("Base");
modelBuilder.Entity<Base_195898>().Property(d => d.Id).HasColumnName("base_c");
modelBuilder.Entity<Derived_195898>().ToTable("Derived");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
modelBuilder.Entity<Base_195898>().Property(b => b.Id).HasColumnName("base_c");
modelBuilder.Entity<Base_195898>().Property(b => b.Complex.Foo).HasColumnName("base_foo");
modelBuilder.Entity<Derived_195898>().Property(d => d.Id).HasColumnName("base_c");
modelBuilder.Entity<Derived_195898>().Property(d => d.Complex.Foo).HasColumnName("base_foo");
}
[Fact]
public void Columns_should_get_preferred_names_when_distinct_in_target_table()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<BaseEntityDuplicateProps>().ToTable("BaseEntities");
modelBuilder.Entity<Entity1DuplicateProps>().ToTable("Entity1s");
modelBuilder.Entity<Entity2DuplicateProps>().ToTable("Entity2s");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<Entity1DuplicateProps>(e => e.SomeProperty).DbEqual("SomeProperty", c => c.Name);
databaseMapping.Assert<Entity2DuplicateProps>(e => e.SomeProperty).DbEqual("SomeProperty", c => c.Name);
}
[Fact]
public void Columns_should_get_configured_names_when_distinct_in_target_table()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<BaseEntityDuplicateProps>().ToTable("BaseEntities");
modelBuilder.Entity<Entity1DuplicateProps>().ToTable("Entity1s");
modelBuilder.Entity<Entity2DuplicateProps>().ToTable("Entity2s");
modelBuilder.Entity<Entity1DuplicateProps>().Property(e => e.SomeProperty).HasColumnName("Foo");
modelBuilder.Entity<Entity2DuplicateProps>().Property(e => e.SomeProperty).HasColumnName("Foo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<Entity1DuplicateProps>(e => e.SomeProperty).DbEqual("Foo", c => c.Name);
databaseMapping.Assert<Entity2DuplicateProps>(e => e.SomeProperty).DbEqual("Foo", c => c.Name);
}
[Fact]
public void Build_model_for_simple_tpt()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>();
modelBuilder.Entity<ColoredProduct>().ToTable("ColoredProducts");
modelBuilder.Entity<StyledProduct>().ToTable("StyledProducts");
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Build_model_for_tpt_tph()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>().ToTable("Products");
modelBuilder.Entity<DiscontinuedProduct>().ToTable("DiscontinuedProducts");
modelBuilder.Entity<StyledProduct>()
.Map(
m =>
{
m.Requires("disc").HasValue("S");
m.ToTable("StyledProducts");
});
modelBuilder.Entity<ColoredProduct>()
.Map(
m =>
{
m.Requires("disc").HasValue("C");
m.ToTable("StyledProducts");
});
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Build_model_for_split_tpt_tph()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>();
modelBuilder.Entity<DiscontinuedProduct>();
modelBuilder.Entity<StyledProduct>().ToTable("StyledProducts");
modelBuilder.Entity<ColoredProduct>();
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Build_model_for_tpc_with_default_tph_in_part_of_tree()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>();
modelBuilder.Entity<DiscontinuedProduct>();
modelBuilder.Entity<StyledProduct>()
.Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("StyledProducts");
});
Assert.Throws<NotSupportedException>(
() => BuildMapping(modelBuilder));
}
[Fact]
public void Build_model_for_three_level_abstract_types_tpt()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<AbstractType1>().HasKey(a => a.Property1_ID).ToTable("AbstractType1");
modelBuilder.Entity<AbstractType1_1>().ToTable("AbstractType1_1");
modelBuilder.Entity<ConcreteType1_1_1>().ToTable("ConcreteType1_1_1");
modelBuilder.Entity<ConcreteType1_2>().ToTable("ConcreteType1_2");
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Build_model_for_tree_containing_only_abstract_types()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<AbstractType1>().HasKey(a => a.Property1_ID);
modelBuilder.Entity<AbstractType1_1>().ToTable("AbstractType1_1");
Assert.Throws<InvalidOperationException>(() => BuildMapping(modelBuilder));
}
[Fact]
public void Build_model_for_entity_splitting()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Vendor>()
.Map(
m =>
{
m.Properties(
v1 => new
{
v1.VendorID,
v1.Name,
v1.PreferredVendorStatus,
v1.AccountNumber,
v1.ActiveFlag,
v1.CreditRating
});
m.ToTable("Vendor");
})
.Map(
m =>
{
m.Properties(
v2 => new
{
v2.VendorID,
v2.ModifiedDate,
v2.PurchasingWebServiceURL
});
m.ToTable("VendorDetails");
});
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Build_model_for_entity_splitting_excluding_key()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Vendor>()
.Map(
m =>
{
m.Properties(
v1 => new
{
v1.VendorID,
v1.Name,
v1.PreferredVendorStatus,
v1.AccountNumber,
v1.ActiveFlag,
v1.CreditRating
});
m.ToTable("Vendor");
})
.Map(
m =>
{
m.Properties(
v2 => new
{
v2.ModifiedDate,
v2.PurchasingWebServiceURL
});
m.ToTable("VendorDetails");
});
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Build_model_for_entity_splitting_with_complex_properties()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<ProductDescription>();
modelBuilder.ComplexType<RowDetails>();
modelBuilder.Entity<ProductDescription>()
.Map(
m =>
{
m.Properties(
pd1 => new
{
pd1.ProductDescriptionID,
pd1.RowDetails.rowguid
});
m.ToTable("ProductDescription");
})
.Map(
m =>
{
m.Properties(
pd2 => new
{
pd2.ProductDescriptionID,
pd2.Description,
pd2.RowDetails.ModifiedDate
});
m.ToTable("ProductDescriptionExtended");
});
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
}
[Fact]
public void Base_type_discovered_by_reachability_is_mapped()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<ITBar>();
modelBuilder.Entity<ITBaz>();
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal(2, databaseMapping.Model.Containers.Single().EntitySets.Count);
Assert.Equal(
"ITFoo",
databaseMapping.Model.Containers.Single().EntitySets.Single(es => es.Name == "ITFoos").
ElementType.Name);
Assert.Equal(3, databaseMapping.Model.EntityTypes.Count());
//Base type with 1 prop
Assert.Equal(
1,
databaseMapping.Model.EntityTypes.Single(et => et.Name == "ITFoo").
DeclaredProperties.Count);
Assert.Equal(
1,
databaseMapping.Model.EntityTypes.Single(et => et.Name == "ITFoo").
Properties.Count());
//Derived type with 1 prop, 0 declared
Assert.Equal(
0,
databaseMapping.Model.EntityTypes.Single(et => et.Name == "ITBar").
DeclaredProperties.Count);
Assert.Equal(
1,
databaseMapping.Model.EntityTypes.Single(et => et.Name == "ITBar").
Properties.Count());
}
[Fact]
public void Abstract_type_at_base_of_TPH_gets_IsTypeOf_mapping()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A1>().Map<A2>(m => { m.Requires("disc").HasValue("A2"); }).Map<A3>(
m => { m.Requires("disc").HasValue("A3"); }).Map<A4>(m => { m.Requires("disc").HasValue("A4"); }).
ToTable("A1");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal(1, databaseMapping.EntityContainerMappings[0].EntitySetMappings.Count());
Assert.Equal(4, databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Count());
Assert.True(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "A1").IsHierarchyMapping);
Assert.False(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "A2").IsHierarchyMapping);
Assert.False(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "A3").IsHierarchyMapping);
Assert.False(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "A4").IsHierarchyMapping);
}
//[Fact]
// Still fails, investigating issue
public void Abstract_type_in_middle_of_TPH_gets_IsTypeOf_mapping()
{
var modelBuilder = new DbModelBuilder();
//modelBuilder.Entity<B1>().Map<B2>(m =>
//{
// m.Requires("disc").HasValue("B2");
//}).Map<B3>(m =>
//{
// m.Requires("disc").HasValue("B3");
//}).ToTable("B1");
modelBuilder.Entity<B1>();
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal(1, databaseMapping.EntityContainerMappings[0].EntitySetMappings.Count());
Assert.Equal(3, databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Count());
Assert.False(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "B1").IsHierarchyMapping);
Assert.True(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "B2").IsHierarchyMapping);
Assert.False(
databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings.Single(
x => x.EntityType.Name == "B3").IsHierarchyMapping);
}
[Fact]
public void Mapping_IA_FK_to_derived_type_puts_FK_in_correct_TPT_table()
{
var modelBuilder = new DbModelBuilder();
// Map to TPT
modelBuilder.Entity<ITOffice>();
modelBuilder.Entity<ITEmployee>().ToTable("Employees");
modelBuilder.Entity<ITOffSiteEmployee>().ToTable("OffSiteEmployees");
modelBuilder.Entity<ITOnSiteEmployee>().ToTable("OnSiteEmployees");
modelBuilder.Entity<ITOnSiteEmployee>()
.HasRequired(e => e.ITOffice);
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<ITEmployee>().DbEqual("Employees", t => t.Table);
databaseMapping.Assert<ITOffSiteEmployee>().DbEqual("OffSiteEmployees", t => t.Table);
databaseMapping.Assert<ITOnSiteEmployee>().DbEqual("OnSiteEmployees", t => t.Table);
// IA FK was properly moved
databaseMapping.Assert<ITEmployee>().HasNoForeignKeyColumn("ITOffice_ITOfficeId");
databaseMapping.Assert<ITOnSiteEmployee>().HasForeignKeyColumn("ITOffice_ITOfficeId");
// AssociationSet mapping updated properly
Assert.Equal(
"OnSiteEmployees",
databaseMapping.Database.GetEntitySet(
databaseMapping.EntityContainerMappings[0].AssociationSetMappings.ElementAt(0).Table).Table);
Assert.Equal(
"ITOffice_ITOfficeId",
databaseMapping.EntityContainerMappings[0].AssociationSetMappings.ElementAt(0).SourceEndMapping
.PropertyMappings.ElementAt(0).ColumnProperty.Name);
}
[Fact]
public void Mapping_FK_to_derived_type_puts_FK_in_correct_TPT_table()
{
var modelBuilder = new DbModelBuilder();
// Map to TPT
modelBuilder.Entity<IT_Office>();
modelBuilder.Entity<IT_Employee>().ToTable("Employees");
modelBuilder.Entity<IT_OffSiteEmployee>().ToTable("OffSiteEmployees");
modelBuilder.Entity<IT_OnSiteEmployee>().ToTable("OnSiteEmployees");
modelBuilder.Entity<IT_OnSiteEmployee>()
.HasRequired(e => e.IT_Office);
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<IT_Employee>().DbEqual("Employees", t => t.Table);
databaseMapping.Assert<IT_OffSiteEmployee>().DbEqual("OffSiteEmployees", t => t.Table);
databaseMapping.Assert<IT_OnSiteEmployee>().DbEqual("OnSiteEmployees", t => t.Table);
databaseMapping.Assert<IT_Employee>().HasNoForeignKeyColumn("IT_OfficeId");
databaseMapping.Assert<IT_OnSiteEmployee>().HasForeignKeyColumn("IT_OfficeId");
Assert.Equal(0, databaseMapping.EntityContainerMappings[0].AssociationSetMappings.Count());
}
[Fact]
public void Mapping_association_to_subtype_by_convention_and_TPH_uses_correct_entity_sets()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<C1>();
modelBuilder.Entity<D1>();
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal("C1", databaseMapping.Model.Containers.Single().AssociationSets[0].SourceSet.Name);
Assert.Equal("D1", databaseMapping.Model.Containers.Single().AssociationSets[0].TargetSet.Name);
}
[Fact]
public void Mapping_association_to_subtype_by_configuration_and_TPH_uses_correct_entity_sets()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<C1>().HasRequired(g => g.DiscontinueD1).WithOptional();
modelBuilder.Entity<D1>();
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal("C1", databaseMapping.Model.Containers.Single().AssociationSets[0].SourceSet.Name);
Assert.Equal("D1", databaseMapping.Model.Containers.Single().AssociationSets[0].TargetSet.Name);
}
[Fact]
public void TPT_model_can_map_PK_property_to_different_columns_in_different_tables()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>();
modelBuilder.Entity<ColoredProduct>().ToTable("ColoredProducts");
modelBuilder.Entity<StyledProduct>().ToTable("StyledProducts");
SetDerivedEntityColumnNames(modelBuilder);
ValidateTPTOrTPCWithRenamedColumns(modelBuilder);
}
[Fact]
public void TPT_model_using_Map_can_map_PK_property_to_different_columns_in_different_tables()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>();
modelBuilder.Entity<ColoredProduct>().Map(m => m.ToTable("ColoredProducts"));
modelBuilder.Entity<StyledProduct>().Map(m => m.ToTable("StyledProducts"));
SetDerivedEntityColumnNames(modelBuilder);
ValidateTPTOrTPCWithRenamedColumns(modelBuilder);
}
[Fact]
public void TPT_model_with_HasColumnName_done_before_ToTable_can_map_PK_property_to_different_columns_in_different_tables()
{
var modelBuilder = new AdventureWorksModelBuilder();
SetDerivedEntityColumnNames(modelBuilder);
modelBuilder.Entity<Product>();
modelBuilder.Entity<ColoredProduct>().ToTable("ColoredProducts");
modelBuilder.Entity<StyledProduct>().ToTable("StyledProducts");
ValidateTPTOrTPCWithRenamedColumns(modelBuilder);
}
[Fact]
public void TPC_model_can_map_PK_property_to_different_columns_in_different_tables()
{
var modelBuilder = new AdventureWorksModelBuilder();
modelBuilder.Entity<Product>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("Products");
});
modelBuilder.Entity<ColoredProduct>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("ColoredProducts");
});
modelBuilder.Entity<StyledProduct>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("StyledProducts");
});
SetDerivedEntityColumnNames(modelBuilder);
ValidateTPTOrTPCWithRenamedColumns(modelBuilder);
}
[Fact]
public void TPC_model_with_HasColumnName_done_before_ToTable_can_map_PK_property_to_different_columns_in_different_tables()
{
var modelBuilder = new AdventureWorksModelBuilder();
SetDerivedEntityColumnNames(modelBuilder);
modelBuilder.Entity<Product>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("Products");
});
modelBuilder.Entity<ColoredProduct>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("ColoredProducts");
});
modelBuilder.Entity<StyledProduct>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("StyledProducts");
});
ValidateTPTOrTPCWithRenamedColumns(modelBuilder);
}
private void SetDerivedEntityColumnNames(AdventureWorksModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>().Property(p => p.ProductID).HasColumnName("base_product_id");
modelBuilder.Entity<ColoredProduct>().Property(p => p.ProductID).HasColumnName("colored_product_id");
modelBuilder.Entity<StyledProduct>().Property(p => p.ProductID).HasColumnName("styled_product_id");
}
private void ValidateTPTOrTPCWithRenamedColumns(AdventureWorksModelBuilder modelBuilder)
{
var databaseMapping = BuildMapping(modelBuilder);
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
databaseMapping.Assert<Product>(p => p.ProductID).DbEqual("base_product_id", c => c.Name);
databaseMapping.Assert<ColoredProduct>(p => p.ProductID).DbEqual("colored_product_id", c => c.Name);
databaseMapping.Assert<StyledProduct>(p => p.ProductID).DbEqual("styled_product_id", c => c.Name);
}
[Fact]
public void TPT_model_using_Table_attributes_can_map_PK_property_to_different_columns_in_different_tables()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<TPTHorse>().Property(e => e.Id).HasColumnName("horse_id");
modelBuilder.Entity<TPTUnicorn>().Property(e => e.Id).HasColumnName("unicorn_id");
modelBuilder.Entity<TPTHornedPegasus>().Property(e => e.Id).HasColumnName("pegasus_id");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
Assert.Equal(1, databaseMapping.EntityContainerMappings.Single().EntitySetMappings.Count());
databaseMapping.Assert<TPTHorse>(p => p.Id).DbEqual("horse_id", c => c.Name);
databaseMapping.Assert<TPTUnicorn>(p => p.Id).DbEqual("unicorn_id", c => c.Name);
databaseMapping.Assert<TPTHornedPegasus>(p => p.Id).DbEqual("pegasus_id", c => c.Name);
}
[Fact]
public void TPT_model_with_PK_property_to_different_columns_in_different_tables_roundtrips()
{
TPT_or_TPC_model_with_PK_property_to_different_columns_in_different_tables_roundtrips<ContextForPkNamingTPT>();
}
[Fact]
public void TPC_model_with_PK_property_to_different_columns_in_different_tables_roundtrips()
{
TPT_or_TPC_model_with_PK_property_to_different_columns_in_different_tables_roundtrips<ContextForPkNamingTPC>();
}
private void TPT_or_TPC_model_with_PK_property_to_different_columns_in_different_tables_roundtrips<TContext>()
where TContext : BaseContextForPkNaming, new()
{
using (var context = new TContext())
{
context.Database.Initialize(force: false);
using (new TransactionScope())
{
var baseEntity = context.Bases.Add(
new BaseForPKNaming
{
Id = 1,
Foo = "Foo1"
});
var derivedEntity =
context.Deriveds.Add(
new DerivedForPKNaming
{
Id = 2,
Foo = "Foo2",
Bar = "Bar2"
});
context.SaveChanges();
context.Entry(baseEntity).State = EntityState.Detached;
context.Entry(derivedEntity).State = EntityState.Detached;
var foundBase = context.Bases.Single(e => e.Id == baseEntity.Id);
var foundDerived = context.Deriveds.Single(e => e.Id == derivedEntity.Id);
Assert.Equal("Foo1", foundBase.Foo);
Assert.Equal("Foo2", foundDerived.Foo);
Assert.Equal("Bar2", foundDerived.Bar);
Assert.True(context.Database.SqlQuery<int>("select base_id from base_table").Any());
Assert.True(context.Database.SqlQuery<int>("select derived_id from derived_table").Any());
if (typeof(TContext)
== typeof(ContextForPkNamingTPC))
{
Assert.True(context.Database.SqlQuery<string>("select base_foo from base_table").Any());
Assert.True(context.Database.SqlQuery<string>("select derived_foo from derived_table").Any());
}
}
}
}
}
#region Fixtures
public abstract class ITFoo
{
public int Id { get; set; }
}
public class ITBar : ITFoo
{
}
public class ITBaz
{
public int Id { get; set; }
public ICollection<ITFoo> ITFoos { get; set; }
}
public abstract class A1
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public int Age1 { get; set; }
public string Name1 { get; set; }
}
public class A2 : A1
{
public int Age2 { get; set; }
public string Name2 { get; set; }
}
public class A3 : A2
{
public int Age3 { get; set; }
public string Name3 { get; set; }
}
public class A4 : A1
{
public int Age4 { get; set; }
public string Name4 { get; set; }
}
public class B1
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public int Age1 { get; set; }
public string Name1 { get; set; }
}
public abstract class B2 : B1
{
public int Age2 { get; set; }
public string Name2 { get; set; }
}
public class B3 : B2
{
public int Age3 { get; set; }
public string Name3 { get; set; }
}
public class ITOffice
{
public int ITOfficeId { get; set; }
public string Name { get; set; }
}
public class ITEmployee
{
public int ITEmployeeId { get; set; }
public string Name { get; set; }
}
public class ITOnSiteEmployee : ITEmployee
{
public ITOffice ITOffice { get; set; }
}
public class ITOffSiteEmployee : ITEmployee
{
public string SiteName { get; set; }
}
public class IT_Office
{
public int IT_OfficeId { get; set; }
public string Name { get; set; }
}
public class IT_Employee
{
public int IT_EmployeeId { get; set; }
public string Name { get; set; }
}
public class IT_OnSiteEmployee : IT_Employee
{
public int IT_OfficeId { get; set; }
public IT_Office IT_Office { get; set; }
}
public class IT_OffSiteEmployee : IT_Employee
{
public string SiteName { get; set; }
}
public class IT_Context : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<IT_Office>();
modelBuilder.Entity<IT_Employee>().ToTable("Employees");
modelBuilder.Entity<IT_OffSiteEmployee>().ToTable("OffSiteEmployees");
modelBuilder.Entity<IT_OnSiteEmployee>().ToTable("OnSiteEmployees");
modelBuilder.Entity<IT_OnSiteEmployee>()
.HasRequired(e => e.IT_Office);
}
public DbSet<IT_Office> Offices { get; set; }
public DbSet<IT_Employee> Employees { get; set; }
}
public abstract class D1
{
public int D1Id { get; set; }
}
public class DiscontinueD1 : D1
{
public DateTime DiscontinuedOn { get; set; }
}
public class C1
{
public int Id { get; set; }
public int DiscontinueD1Id { get; set; }
public DiscontinueD1 DiscontinueD1 { get; set; }
}
public class BaseEntityDuplicateProps
{
public int ID { get; set; }
public string Title { get; set; }
}
public class Entity1DuplicateProps : BaseEntityDuplicateProps
{
public string SomeProperty { get; set; }
public int Entity2ID { get; set; }
public Entity2DuplicateProps Entity2 { get; set; }
}
public class Entity2DuplicateProps : BaseEntityDuplicateProps
{
public string SomeProperty { get; set; }
}
public class Base_195898
{
public int Id { get; set; }
public Complex_195898 Complex { get; set; }
}
public class Derived_195898 : Base_195898
{
}
public class Complex_195898
{
public string Foo { get; set; }
}
public abstract class BaseDependent_165027
{
public decimal? BaseProperty { get; set; }
public float? Key1 { get; set; }
public decimal? Key2 { get; set; }
}
public class Dependent_165027 : BaseDependent_165027
{
}
#endregion
#region Bug DevDiv#223284
namespace Bug223284
{
public class ITEmployee : FunctionalTests.ITEmployee
{
public ITOffice ITOffice { get; set; }
}
public class IT_Context : DbContext
{
public DbSet<ITEmployee> Employees { get; set; }
}
public sealed class Bug223284Test : FunctionalTestBase
{
[Fact]
public void Duplicate_entity_name_different_namespace_should_throw()
{
var context = new IT_Context();
Assert.Throws<InvalidOperationException>(() => context.Employees.Add(new ITEmployee())).
ValidateMessage("InvalidEntityType", "FunctionalTests.Bug223284.ITEmployee");
}
}
}
#endregion
#region Bug DevDiv#175804
namespace Bug175804
{
public class Dependent
{
public int principalnavigationkey1 { get; set; }
public int Id { get; set; }
public Principal PrincipalNavigation { get; set; }
}
public class Principal : BasePrincipal
{
}
public class DerivedDependent : Dependent
{
public decimal DependentDerivedProperty1 { get; set; }
}
public class BasePrincipal
{
public DateTime BaseProperty { get; set; }
public int Key1 { get; set; }
}
public sealed class Bug175804Test : FunctionalTestBase
{
[Fact]
public void TPC_Ordering_Of_Configuration_Between_Related_Types()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Dependent>().HasRequired(e => e.PrincipalNavigation);
modelBuilder.Entity<BasePrincipal>().HasKey(e => e.Key1);
modelBuilder.Entity<DerivedDependent>().Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("DerivedDependent");
});
modelBuilder.Entity<Principal>().Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("Principal");
});
modelBuilder.Entity<Dependent>().Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("Dependent");
});
modelBuilder.Entity<BasePrincipal>().Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("BasePrincipal");
});
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
var derivedTypeMappings =
databaseMapping.EntityContainerMappings[0].EntitySetMappings
.First(es => es.EntitySet.Name.Contains("Dependent")).EntityTypeMappings;
Assert.Equal(
"Principal",
derivedTypeMappings.ElementAt(0).MappingFragments[0].Table.ForeignKeyBuilders.ElementAt(0).
PrincipalTable.Name);
Assert.Equal(
"Principal",
derivedTypeMappings.ElementAt(1).MappingFragments[0].Table.ForeignKeyBuilders.ElementAt(0).
PrincipalTable.Name);
}
}
}
#endregion
#region BugDevDiv#178590
namespace BugDevDiv_178590
{
public abstract class A
{
public virtual int Id { get; set; }
public virtual int? X { get; set; }
}
public abstract class B : A
{
public virtual int? Y { get; set; }
}
public class C : B
{
public virtual int? Z { get; set; }
}
#region Subclasses have no extra properties
public abstract class D
{
public virtual int Id { get; set; }
public virtual int? X { get; set; }
}
public class E : D
{
}
public class F : E
{
}
#endregion
public sealed class Bug178590Test : FunctionalTestBase
{
[Fact]
public void AbstractClasses_TPC()
{
var modelBuilder = new DbModelBuilder();
// add .ToTable("B", "dbo") as workaround
modelBuilder.Entity<A>();
modelBuilder
.Entity<B>()
.Map(mapping => mapping.MapInheritedProperties())
;
modelBuilder
.Entity<C>()
.Map(mapping => mapping.MapInheritedProperties())
.ToTable("C", "dbo")
;
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
var typeMappings = databaseMapping.EntityContainerMappings[0].EntitySetMappings.ElementAt(0).EntityTypeMappings;
Assert.Equal(1, typeMappings.Count());
Assert.Equal("C", typeMappings.ElementAt(0).EntityType.Name);
Assert.Equal(1, typeMappings.ElementAt(0).MappingFragments.Count);
Assert.Equal(4, typeMappings.ElementAt(0).MappingFragments[0].ColumnMappings.Count());
}
[Fact]
public void AbstractClasses_TPT()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A>();
modelBuilder
.Entity<B>()
.Map(mapping => mapping.MapInheritedProperties());
modelBuilder
.Entity<C>()
.ToTable("C", "dbo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
}
[Fact]
public void SubClasses_NoProperties()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<D>();
modelBuilder.Entity<E>();
modelBuilder.Entity<F>();
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
}
}
}
#endregion
#region Bug165027
namespace Bug165027
{
public class Dependent1
{
public DateTimeOffset key1 { get; set; }
public Principal1 PrincipalNavigation { get; set; }
}
public abstract class Principal1 : BasePrincipal1
{
public Dependent1 DependentNavigation { get; set; }
}
public class BasePrincipal1
{
public short BaseProperty { get; set; }
public DateTimeOffset? Key1 { get; set; }
}
public class DerivedPrincipal1 : Principal1
{
public decimal PrincipalDerivedProperty1 { get; set; }
}
public sealed class Bug165027Repro : FunctionalTestBase
{
[Fact]
public void Bug165027Test()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<BasePrincipal1>().ToTable("BasePrincipal");
modelBuilder.Entity<BasePrincipal1>().HasKey(e => e.Key1);
modelBuilder.Entity<Principal1>().HasOptional(e => e.DependentNavigation).WithRequired(
e => e.PrincipalNavigation);
modelBuilder.Entity<DerivedPrincipal1>().Map(
mapping =>
{
mapping.MapInheritedProperties();
mapping.ToTable("DerivedPrincipal");
});
modelBuilder.Entity<Dependent1>().HasKey(e => e.key1);
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
}
}
}
#endregion
#region Bug178568
namespace Bug178568
{
using System.Data.Entity.Core.Metadata.Edm;
public abstract class A
{
public virtual int Id { get; set; }
public virtual int? X { get; set; }
}
public class B : A
{
public virtual int? Y { get; set; }
}
public class C
{
public virtual int Id { get; set; }
public virtual int? X { get; set; }
public virtual int? Y { get; set; }
}
public sealed class Bug178568Repro : TestBase
{
[Fact]
public void TPC_Identity_ShouldPropagate()
{
var modelBuilder = new DbModelBuilder();
modelBuilder
.Entity<A>()
.HasKey(a => a.Id);
modelBuilder
.Entity<A>()
.Property(a => a.Id)
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder
.Entity<B>()
.Map(mapping => mapping.MapInheritedProperties())
.ToTable("B", "dbo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<B>("B")
.Column("Id").DbEqual(
StoreGeneratedPattern.Identity,
c => c.StoreGeneratedPattern);
}
[Fact]
public void TPC_IdentityNotExplicit_ShouldNotPropagate()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A>();
modelBuilder
.Entity<B>()
.Map(mapping => mapping.MapInheritedProperties())
.ToTable("B", "dbo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<B>("B")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
[Fact]
public void TPT_Identity_ShouldNotPropagate()
{
var modelBuilder = new DbModelBuilder();
modelBuilder
.Entity<A>()
.HasKey(a => a.Id);
modelBuilder
.Entity<A>()
.Property(a => a.Id)
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder
.Entity<B>()
.ToTable("B", "dbo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<A>("A")
.Column("Id").DbEqual(
StoreGeneratedPattern.Identity,
c => c.StoreGeneratedPattern);
databaseMapping.Assert<B>("B")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
[Fact]
public void EntitySplitting_Identity_ShouldNotPropagate()
{
var modelBuilder = new DbModelBuilder();
modelBuilder
.Entity<C>()
.HasKey(a => a.Id);
modelBuilder
.Entity<C>()
.Property(a => a.Id)
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<C>()
.Map(
m =>
{
m.Properties(
c => new
{
c.Id,
c.X
});
m.ToTable("CX");
})
.Map(
m =>
{
m.Properties(
c => new
{
c.Id,
c.Y
});
m.ToTable("CY");
});
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<C>("CX")
.Column("Id").DbEqual(
StoreGeneratedPattern.Identity,
c => c.StoreGeneratedPattern);
databaseMapping.Assert<C>("CY")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
}
}
#endregion
#region Bug336566
namespace Bug336566
{
using System.Data.Entity.Core.Metadata.Edm;
public class A
{
public virtual int Id { get; set; }
public virtual int? X { get; set; }
}
public class B : A
{
public virtual int? Y { get; set; }
}
public class C
{
public virtual int Id { get; set; }
public virtual int? X { get; set; }
public virtual int? Y { get; set; }
}
public sealed class Bug336566Repro : TestBase
{
[Fact]
public void TPC_IdentityNotExplicit_ShouldNotPropagate()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A>();
modelBuilder
.Entity<B>()
.Map(mapping => mapping.MapInheritedProperties())
.ToTable("B", "dbo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<A>("A")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
databaseMapping.Assert<B>("B")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
[Fact]
public void NoIdentityExplicit()
{
var modelBuilder = new DbModelBuilder();
modelBuilder
.Entity<A>()
.Property(a => a.Id)
.IsRequired()
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<A>("A")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
[Fact]
public void TPT_Identity_ShouldKickIn()
{
var modelBuilder = new DbModelBuilder();
modelBuilder
.Entity<A>();
modelBuilder
.Entity<B>()
.ToTable("B", "dbo");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<A>("A")
.Column("Id").DbEqual(
StoreGeneratedPattern.Identity,
c => c.StoreGeneratedPattern);
databaseMapping.Assert<B>("B")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
[Fact]
public void EntitySplitting_Identity_ShouldKickIn()
{
var modelBuilder = new DbModelBuilder();
modelBuilder
.Entity<C>()
.HasKey(a => a.Id);
modelBuilder.Entity<C>()
.Map(
m =>
{
m.Properties(
c => new
{
c.Id,
c.X
});
m.ToTable("CX");
})
.Map(
m =>
{
m.Properties(
c => new
{
c.Id,
c.Y
});
m.ToTable("CY");
});
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<C>("CX")
.Column("Id").DbEqual(
StoreGeneratedPattern.Identity,
c => c.StoreGeneratedPattern);
databaseMapping.Assert<C>("CY")
.Column("Id").DbEqual(
StoreGeneratedPattern.None,
c => c.StoreGeneratedPattern);
}
}
}
#endregion
#region Contexts for TPT/TPC with different PK column names
public abstract class BaseContextForPkNaming : DbContext
{
public DbSet<BaseForPKNaming> Bases { get; set; }
public DbSet<DerivedForPKNaming> Deriveds { get; set; }
}
public class ContextForPkNamingTPC : BaseContextForPkNaming
{
public ContextForPkNamingTPC()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ContextForPkNamingTPC>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseForPKNaming>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("base_table");
});
modelBuilder.Entity<DerivedForPKNaming>().Map(
m =>
{
m.MapInheritedProperties();
m.ToTable("derived_table");
});
modelBuilder.Entity<BaseForPKNaming>().Property(e => e.Id).HasColumnName("base_id");
modelBuilder.Entity<DerivedForPKNaming>().Property(e => e.Id).HasColumnName("derived_id");
modelBuilder.Entity<BaseForPKNaming>().Property(e => e.Foo).HasColumnName("base_foo");
modelBuilder.Entity<DerivedForPKNaming>().Property(e => e.Foo).HasColumnName("derived_foo");
}
}
public class ContextForPkNamingTPT : BaseContextForPkNaming
{
public ContextForPkNamingTPT()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<ContextForPkNamingTPT>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseForPKNaming>().ToTable("base_table");
modelBuilder.Entity<DerivedForPKNaming>().ToTable("derived_table");
modelBuilder.Entity<BaseForPKNaming>().Property(e => e.Id).HasColumnName("base_id");
modelBuilder.Entity<DerivedForPKNaming>().Property(e => e.Id).HasColumnName("derived_id");
}
}
public class BaseForPKNaming
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Foo { get; set; }
}
public class DerivedForPKNaming : BaseForPKNaming
{
public string Bar { get; set; }
}
[Table("Horses")]
public class TPTHorse
{
public int Id { get; set; }
}
[Table("Unicorns")]
public class TPTUnicorn : TPTHorse
{
public int HornLength { get; set; }
}
[Table("HornedPegasuses")]
public class TPTHornedPegasus : TPTUnicorn
{
public int Wingspan { get; set; }
}
#endregion
#region Bug335965
namespace Bug335965
{
using System.Data.Entity.Core;
public class A
{
public int Id { get; set; }
public string X { get; set; }
}
public abstract class B : A
{
public string Y { get; set; }
}
public class C : B
{
public string Z { get; set; }
}
public class A2
{
public int Id { get; set; }
public string X { get; set; }
}
public abstract class B2 : A2
{
public string Y { get; set; }
}
public class C2 : B2
{
public string Z { get; set; }
}
public class D2 : B2
{
public string W { get; set; }
}
public sealed class Bug335965Repro : TestBase
{
[Fact]
public void ExplicitDiscriminatorShouldNotBeNullable()
{
var modelBuilder = new DbModelBuilder();
// Adding this configuration makes the discriminator nullable.
modelBuilder.Entity<B>();
modelBuilder.Entity<A>().Map(m => m.Requires("Disc").HasValue(17));
modelBuilder.Entity<C>().Map(m => m.Requires("Disc").HasValue(7));
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping
.Assert<A>("A")
.Column("Disc")
.DbEqual(false, c => c.Nullable);
}
[Fact]
public void InvalidMappingSubtypeHasNoDiscriminatorCondition()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A2>().Map(m => m.Requires("Disc").HasValue(17));
modelBuilder.Entity<C2>().Map(m => m.Requires("Disc").HasValue(7));
modelBuilder.Entity<B2>();
modelBuilder.Entity<D2>();
var databaseMapping = BuildMapping(modelBuilder);
Assert.Throws<MappingException>(() => databaseMapping.AssertValid(true));
}
[Fact]
public void ImplicitDiscriminatorShouldNotBeNullable()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A>();
modelBuilder.Entity<C>();
modelBuilder.Entity<B>();
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
databaseMapping.Assert<A>("A")
.Column("Discriminator")
.DbEqual(false, c => c.Nullable);
}
}
}
#endregion
#region Bug339467
namespace Bug339467
{
public class A
{
public int Id { set; get; }
public string Name { set; get; }
}
public abstract class B : A
{
}
public class C : B
{
public string CName { set; get; }
}
public sealed class Bug339467Repro : TestBase
{
[Fact]
public void SimpleTPTWithAbstractWithNoPropertiesInBetween()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<A>();
modelBuilder.Entity<C>().ToTable("C");
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.AssertValid();
}
}
}
#endregion
#region Bug336706
namespace Bug336706
{
public class Dependent : BaseDependent
{
public int PrincipalNavigationId { get; set; }
public BaseDependent PrincipalNavigation { get; set; }
}
public abstract class BaseDependent
{
public int Id { get; set; }
public ICollection<Dependent> DependentNavigation { get; set; }
public BaseDependent()
{
DependentNavigation = new List<Dependent>();
}
}
public sealed class Bug336706Repro : TestBase
{
[Fact]
public void TPH_with_self_ref_FK_on_derived_type_has_non_nullable_FK_when_base_type_is_abstract()
{
var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Dependent>().HasRequired(e => e.PrincipalNavigation).WithMany(
e => e.DependentNavigation)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Dependent>().Map(mapping => { mapping.Requires("DiscriminatorValue").HasValue(1); });
var databaseMapping = BuildMapping(modelBuilder);
databaseMapping.Assert<Dependent>("BaseDependents")
.HasForeignKeyColumn("PrincipalNavigationId")
.DbEqual(false, t => t.Properties.Single(c => c.Name == "PrincipalNavigationId").Nullable);
databaseMapping.AssertValid();
}
}
}
#endregion
}