// 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; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity; using System.Data.Entity.Core.Metadata.Edm; using System.Linq; using System.Linq.Expressions; using FunctionalTests.Model; using Xunit; public class DataAnnotationScenarioTests : TestBase { [Fact] public void Duplicate_column_order_should_not_throw_when_v1_convention_set() { var modelBuilder = new DbModelBuilder(DbModelBuilderVersion.V4_1); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); } [Fact] public void Duplicate_column_order_should_throw_when_v2_convention_set() { var modelBuilder = new DbModelBuilder(DbModelBuilderVersion.V5_0); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("DuplicateConfiguredColumnOrder", "Entity_10558"); } [Fact] public void Non_public_annotations_are_enabled() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity().Property( PrivateMemberAnnotationClass.PersonFirstNameExpr); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(PrivateMemberAnnotationClass.PersonFirstNameObjectExpr) .DbEqual("dsdsd", c => c.Name) .DbEqual("nvarchar", c => c.TypeName) .DbEqual(128, f => f.MaxLength) .DbEqual(true, c => c.IsPrimaryKeyColumn); } [Fact] public void NotMapped_should_propagate_down_inheritance_hierachy() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("InvalidEntityType", typeof(NotMappedDerived)); } [Fact] public void NotMapped_on_base_class_property_ignores_it() { using (var baseEntityConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); baseEntityConfiguration.SetPropertyAttributes(b => b.BaseClassProperty, new NotMappedAttribute()); baseEntityConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.SelectMany(e => e.Properties) .Any(p => p.Name == "BaseClassProperty")); Assert.False( databaseMapping.Model.EntityTypes.SelectMany(e => e.Properties) .Any(p => p.Name == "VirtualBaseClassProperty")); } } [Fact] public void NotMapped_on_base_class_property_and_overriden_property_ignores_them() { using (var baseEntityConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var unitConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); unitConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); baseEntityConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.SelectMany(e => e.Properties) .Any(p => p.Name == "VirtualBaseClassProperty")); } } } [Fact] public void NotMapped_on_base_class_property_discovered_through_navigation_ignores_it() { using (var abstractBaseEntityConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); abstractBaseEntityConfiguration.SetPropertyAttributes(b => b.AbstractBaseClassProperty, new NotMappedAttribute()); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.True(databaseMapping.Model.EntityTypes.Any(e => e.Name == "AbstractBaseEntity")); Assert.False( databaseMapping.Model.EntityTypes.SelectMany(e => e.Properties) .Any(p => p.Name == "AbstractBaseClassProperty")); } } [Fact] public void NotMapped_on_abstract_base_class_property_ignores_it() { using (var abstractBaseEntityConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); abstractBaseEntityConfiguration.SetPropertyAttributes(b => b.AbstractBaseClassProperty, new NotMappedAttribute()); modelBuilder.Entity(); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.SelectMany(e => e.Properties) .Any(p => p.Name == "AbstractBaseClassProperty")); } } [Fact] public void NotMapped_on_overriden_mapped_base_class_property_throws() { using (var unitConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); unitConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Ignore(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws(() => BuildMapping(modelBuilder)) .ValidateMessage( "CannotIgnoreMappedBaseProperty", "VirtualBaseClassProperty", "FunctionalTests.Unit", "FunctionalTests.BaseEntity"); } } [Fact] public void NotMapped_on_unmapped_derived_property_ignores_it() { using (var unitConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); unitConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Ignore(); modelBuilder.Ignore(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.Single().Properties.Any( p => p.Name == "VirtualBaseClassProperty")); } } [Fact] public void NotMapped_on_unmapped_base_class_property_and_overriden_property_ignores_it() { using (var unitConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var baseEntityConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); baseEntityConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); unitConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Ignore(); modelBuilder.Ignore(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.Single().Properties.Any( p => p.Name == "VirtualBaseClassProperty")); } } } [Fact] public void NotMapped_on_unmapped_base_class_property_ignores_it() { using (var baseEntityConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); baseEntityConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Ignore(); modelBuilder.Ignore(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.Single().Properties.Any( p => p.Name == "VirtualBaseClassProperty")); } } [Fact] public void NotMapped_on_new_property_with_same_name_as_in_unmapped_base_class_ignores_it() { using (var differentUnitConfiguration = new DynamicTypeDescriptionConfiguration()) { var modelBuilder = new DbModelBuilder(); differentUnitConfiguration.SetPropertyAttributes(b => b.VirtualBaseClassProperty, new NotMappedAttribute()); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); Assert.False( databaseMapping.Model.EntityTypes.Single().Properties.Any( p => p.Name == "VirtualBaseClassProperty")); } } [Fact] public void MaxLength_takes_presedence_over_StringLength() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.PersonFirstName).FacetEqual(true, a => a.IsMaxLength); } [Fact] public void MaxLength_with_length_takes_precedence_over_StringLength() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.PersonFirstName).FacetEqual( 30, a => a.MaxLength); } [Fact] public void Default_length_for_key_string_column() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.UserName, new KeyAttribute()); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Ignore(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.UserName) .DbEqual("nvarchar", c => c.TypeName) .DbEqual(128, f => f.MaxLength); } } [Fact] public void Key_and_column_work_together() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.PersonFirstName) .DbEqual("dsdsd", c => c.Name) .DbEqual("nvarchar", c => c.TypeName) .DbEqual(128, f => f.MaxLength) .DbEqual(true, c => c.IsPrimaryKeyColumn); } [Fact] // Regression test for Dev11 Bug 87347 public void Key_and_column_work_together_in_an_IA() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.PersonFirstName) .DbEqual("dsdsd", c => c.Name) .DbEqual("nvarchar", c => c.TypeName) .DbEqual(128, f => f.MaxLength) .DbEqual(true, c => c.IsPrimaryKeyColumn); Assert.Equal(1, databaseMapping.Model.AssociationTypes.Count()); databaseMapping.Assert().ForeignKeyColumn("Person_PersonFirstName") .DbEqual("nvarchar", c => c.TypeName) .DbEqual(128, f => f.MaxLength); } [Fact] public void Key_column_and_MaxLength_work_together() { using (var entityClassConfiguration = new DynamicTypeDescriptionConfiguration()) { entityClassConfiguration.SetPropertyAttributes(c => c.PersonFirstName, new MaxLengthAttribute(64)); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.PersonFirstName) .DbEqual("dsdsd", c => c.Name) .DbEqual("nvarchar", c => c.TypeName) .DbEqual(64, f => f.MaxLength) .DbEqual(true, c => c.IsPrimaryKeyColumn); } } [Fact] public void Key_column_and_MaxLength_work_together_in_an_IA() { using (var entityClassConfiguration = new DynamicTypeDescriptionConfiguration()) { entityClassConfiguration.SetPropertyAttributes(c => c.PersonFirstName, new MaxLengthAttribute(64)); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert(x => x.PersonFirstName) .DbEqual("dsdsd", c => c.Name) .DbEqual("nvarchar", c => c.TypeName) .DbEqual(64, f => f.MaxLength) .DbEqual(true, c => c.IsPrimaryKeyColumn); Assert.Equal(1, databaseMapping.Model.AssociationTypes.Count()); databaseMapping.Assert().ForeignKeyColumn("Person_PersonFirstName") .DbEqual("nvarchar", c => c.TypeName) .DbEqual(64, f => f.MaxLength); } } [Fact] public void Key_from_base_type_is_recognized() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); // one thing configured because of key property Assert.Equal(1, modelBuilder.ModelConfiguration.Entity(typeof(OKeyBase)).ConfiguredProperties.Count()); // should be nothing configured on derived type Assert.Equal(0, modelBuilder.ModelConfiguration.Entity(typeof(DODerived)).ConfiguredProperties.Count()); } [Fact] public void Key_on_nav_prop_is_ignored() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert().DbEqual("Id", t => t.DeclaredKeyProperties.Single().Name); } [Fact] public void Timestamp_takes_precedence_over_MaxLength() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity().Ignore(x => x.NonMaxTimestamp); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert().DbEqual( "rowversion", t => t.Properties.Single(x => x.Name == "MaxTimestamp"). TypeName); databaseMapping.Assert().DbEqual( false, t => t.Properties.Single(x => x.Name == "MaxTimestamp").IsMaxLength); databaseMapping.Assert().DbEqual( null, t => t.Properties.Single(x => x.Name == "MaxTimestamp").MaxLength); } [Fact] public void Timestamp_takes_precedence_over_MaxLength_with_value() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity().Ignore(x => x.MaxTimestamp); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); databaseMapping.Assert().DbEqual( "rowversion", t => t.Properties.Single(x => x.Name == "NonMaxTimestamp"). TypeName); databaseMapping.Assert().DbEqual( false, t => t.Properties.Single(x => x.Name == "NonMaxTimestamp").IsMaxLength); databaseMapping.Assert().DbEqual( null, t => t.Properties.Single(x => x.Name == "NonMaxTimestamp").MaxLength); } [Fact] public void Annotation_in_derived_class_when_base_class_processed_after_derived_class() { var modelBuilder = new AdventureWorksModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.Assert(s => s.Style).FacetEqual(150, f => f.MaxLength); } [Fact] public void Required_and_ForeignKey_to_Required() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var profileConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes( l => l.Profile, new RequiredAttribute(), new ForeignKeyAttribute("LoginId")); profileConfiguration.SetPropertyAttributes(p => p.User, new RequiredAttribute()); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Login), typeof(Profile)); } } } [Fact] // Regression test for Dev11 Bug 94993 public void Required_to_Required_and_ForeignKey() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var profileConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.Profile, new RequiredAttribute()); profileConfiguration.SetPropertyAttributes( p => p.User, new RequiredAttribute(), new ForeignKeyAttribute("ProfileId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Login), typeof(Profile)); } } } [Fact] public void Required_and_ForeignKey_to_Required_and_ForeignKey() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var profileConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes( l => l.Profile, new RequiredAttribute(), new ForeignKeyAttribute("LoginId")); profileConfiguration.SetPropertyAttributes( p => p.User, new RequiredAttribute(), new ForeignKeyAttribute("ProfileId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Login), typeof(Profile)); } } } [Fact] public void ForeignKey_to_nothing() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.Profile, new ForeignKeyAttribute("LoginId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Profile), typeof(Login)); } } } [Fact] public void Required_and_ForeignKey_to_nothing() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.Profile, new ForeignKeyAttribute("LoginId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Profile), typeof(Login)); } } } [Fact] public void Nothing_to_ForeignKey() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var profileConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.Profile); profileConfiguration.SetPropertyAttributes(p => p.User, new ForeignKeyAttribute("ProfileId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Profile), typeof(Login)); } } } [Fact] public void Nothing_to_Required_and_ForeignKey() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var profileConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.Profile); profileConfiguration.SetPropertyAttributes( p => p.User, new RequiredAttribute(), new ForeignKeyAttribute("ProfileId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.AssertValid(); var association = databaseMapping.Model.AssociationTypes.Single(); Assert.Equal("Profile", association.SourceEnd.GetEntityType().Name); Assert.Equal(RelationshipMultiplicity.ZeroOrOne, association.SourceEnd.RelationshipMultiplicity); Assert.Equal("Login", association.TargetEnd.GetEntityType().Name); Assert.Equal(RelationshipMultiplicity.One, association.TargetEnd.RelationshipMultiplicity); Assert.Equal("Profile", association.Constraint.ToRole.GetEntityType().Name); } } } [Fact] public void ForeignKey_to_ForeignKey() { using (var loginConfiguration = new DynamicTypeDescriptionConfiguration()) { using (var profileConfiguration = new DynamicTypeDescriptionConfiguration()) { loginConfiguration.SetPropertyAttributes(l => l.Profile, new ForeignKeyAttribute("LoginId")); profileConfiguration.SetPropertyAttributes(p => p.User, new ForeignKeyAttribute("ProfileId")); var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); Assert.Throws( () => BuildMapping(modelBuilder)) .ValidateMessage("UnableToDeterminePrincipal", typeof(Profile), typeof(Login)); } } } [Fact] public void TableNameAttribute_affects_only_base_in_TPT() { var modelBuilder = new AdventureWorksModelBuilder(); modelBuilder.Entity() .Map(mc => mc.ToTable("B")); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.Assert("A"); databaseMapping.Assert("B"); } [Fact] public void TableNameAttribute_affects_table_name_in_TPH() { var modelBuilder = new AdventureWorksModelBuilder(); modelBuilder.Entity() .Map(mc => mc.Requires("disc").HasValue("A")) .Map(mc => mc.Requires("disc").HasValue("B")); var databaseMapping = BuildMapping(modelBuilder); databaseMapping.Assert("A"); databaseMapping.AssertMapping("A", false).HasColumnCondition("disc", "A"); databaseMapping.Assert("A"); databaseMapping.AssertMapping("A").HasColumnCondition("disc", "B"); } } #region Fixtures public class MaxLengthAnnotationClass { public int Id { get; set; } [StringLength(500)] [MaxLength] public string PersonFirstName { get; set; } } public class MaxLengthWithLengthAnnotationClass { public int Id { get; set; } [StringLength(500)] [MaxLength(30)] public string PersonFirstName { get; set; } } public class ColumnKeyAnnotationClass { [Key] [Column("dsdsd", Order = 1, TypeName = "nvarchar")] public string PersonFirstName { get; set; } } public class ReferencingClass { public int Id { get; set; } public ColumnKeyAnnotationClass Person { get; set; } } public class DASimple { public int Id { get; set; } } public class KeyOnNavProp { public int Id { get; set; } [Key] public ICollection Simples { get; set; } [Key] public DASimple SpecialSimple { get; set; } } public class SRelated { public int SRelatedId { get; set; } public ICollection DADeriveds { get; set; } } public class OKeyBase { [Key] public int OrderLineNo { get; set; } public int Quantity { get; set; } } public class DODerived : OKeyBase { public SRelated DARelated { get; set; } public string Special { get; set; } } public class TimestampAndMaxlen { public int Id { get; set; } [MaxLength] [Timestamp] public byte[] MaxTimestamp { get; set; } [MaxLength(100)] [Timestamp] public byte[] NonMaxTimestamp { get; set; } } public class Login { public int LoginId { get; set; } public string UserName { get; set; } public virtual Profile Profile { get; set; } } public class Profile { public int ProfileId { get; set; } public string Name { get; set; } public string Email { get; set; } public virtual Login User { get; set; } } [Table("A")] public class TNAttrBase { public int Id { get; set; } public string BaseData { get; set; } } public class TNAttrDerived : TNAttrBase { public string DerivedData { get; set; } } [NotMapped] public class NotMappedBase { public int Id { get; set; } } public class NotMappedDerived : NotMappedBase { } public class PrivateMemberAnnotationClass { public static Expression> PersonFirstNameExpr = p => p.PersonFirstName; public static Expression> PersonFirstNameObjectExpr = p => p.PersonFirstName; [Key] [Column("dsdsd", Order = 1, TypeName = "nvarchar")] private string PersonFirstName { get; set; } } public class Entity_10558 { [Key] [Column(Order = 1)] public int Key1 { get; set; } [Key] [Column(Order = 1)] public int Key2 { get; set; } public string Name { get; set; } } #endregion #region Bug324763 namespace Bug324763 { using System.Data.Entity.ModelConfiguration.Conventions; public class Product { [Timestamp] public byte[] Version { get; set; } [Key] [Column(Order = 0)] public int ProductId { get; set; } [Key] [Column(Order = 1)] [MaxLength(128)] public string Sku { get; set; } [Required] [StringLength(15)] public string Name { get; set; } public byte[] Image { get; set; } [InverseProperty("Product")] public ICollection OrderLines { get; set; } } public class OrderLine { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public int OrderId { get; set; } [NotMapped] public short Quantity { get; set; } public decimal Price { get; set; } public decimal Total { get; set; } public bool? IsShipped { get; set; } [ForeignKey("Product")] [Column(Order = 0)] public int ProductIdFk { get; set; } [ForeignKey("Product")] [Column(Order = 1)] public string ProductSkuFk { get; set; } [MaxLength(128)] public string Sku { get; set; } [ConcurrencyCheck] public int EngineSupplierId { get; set; } public Product Product { get; set; } } public class Test324763 : FunctionalTestBase { [Fact] public void Repro324763_Build_Is_Not_Idempotent() { var modelBuilder = new DbModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity(); ValidateBuildIsIdempotent(modelBuilder); } private void ValidateBuildIsIdempotent(DbModelBuilder modelBuilder) { var mapping1 = BuildMapping(modelBuilder); var mapping2 = BuildMapping(modelBuilder); Assert.True(mapping1.EdmxIsEqualTo(mapping2)); } [Fact] public void Repro324763_Build_Is_Not_Idempotent_Inverse() { var modelBuilder = new DbModelBuilder(); modelBuilder.Conventions.Remove(); modelBuilder.Entity(); modelBuilder.Entity(); ValidateBuildIsIdempotent(modelBuilder); } } } #endregion }