0

I've been bumbling along with EF5 but I cant seem to get two domain classes to map to a single database table.

The error I get is:

   Message: "The type 'Basd.Erp.Wms.Purchasing.SupplierProfile' has already been configured as an entity type. It cannot be reconfigured as a complex type."

This is my DbContext:

    public class PurchasingContext : DisconnectedEntityContext
    {
        public DbSet<SupplierCard> Suppliers { get; set; }
        public DbSet<PurchaseCategory> PurchaseCategories { get; set; }

        public PurchasingContext() : this("Basd.Erp.Wms") { }

        public PurchasingContext(string connectionStringName) : base(connectionStringName) { }

        public static PurchasingContext GetInstance(EfDataProvider provider) { return new PurchasingContext(provider.ConnectionStringName); }
    }
}

These are my classes:

namespace Basd.Erp.Wms.Purchasing
{

    public class SupplierCard : ContactCard, ISupplierCard
    {
        private ICollection<PurchaseCategory> _purchaseCategories;

        public ICollection<PurchaseCategory> PurchaseCategories
        {
            get { return _purchaseCategories; }
            set { SetNotifyField(ref _purchaseCategories, value, () => PurchaseCategories); }
        }

        public SupplierProfile Profile { get; protected set; }

        private SupplierCard()
        {
            this.Profile = new SupplierProfile();
            this.PurchaseCategories = new Collection<PurchaseCategory>();
        }

        public SupplierCard(long id, string alf, string name)
            : this(id, alf, new SimpleNameHolder(name), new Collection<IPhysicalAddress>(), new DigitalAddresses()) { }

        public SupplierCard(long id, string alf, INameHolder nameHolder,
                            ICollection<IPhysicalAddress> physicalAddresses, IDigitalAddresses digitalAddresses)
            : this(id, alf, nameHolder, physicalAddresses, digitalAddresses, null) { }

        public SupplierCard(long id, string alf, INameHolder nameHolder,
           ICollection<IPhysicalAddress> physicalAddresses, IDigitalAddresses digitalAddresses, IValidatableObject validator)
            : base(id, alf, nameHolder, physicalAddresses, digitalAddresses, validator)
        {
            this.Profile = new SupplierProfile();
            this.PurchaseCategories = new Collection<PurchaseCategory>();
        }
    }
}

  public class SupplierProfile : AbstractAspect
    {


        private TradingEntity _incType;

        public TradingEntity BusinessType
        {
            get { return _incType; }
            set
            {
                if (_incType != null) { this.DeregisterSubPropertyForChangeTracking(this.BusinessType); }
                _incType = value; this.OnPropertyChanged("TradingType");
                this.RegisterSubPropertyForChangeTracking(this.BusinessType);
            }
        }

        private bool _emailOk;
        private bool _smailOk;

        public bool MarketingEmailOk
        {
            get { return _emailOk; }
            set { _emailOk = value; this.OnPropertyChanged("MarketingEmailOk"); }
        }


        public bool MarketingSmailOk
        {
            get { return _smailOk; }
            set { _smailOk = value; this.OnPropertyChanged("MarketingSmailOk"); }
        }

        public SupplierProfile()
            : base()
        {
            this.BusinessType = new TradingEntity(ContactLegalType.Limited);
        }
    }
}

These are my configuration classes:

 [Export(typeof(IEntityConfiguration))]
    public class SupplierCardConfiguration
        : EntityTypeConfiguration<SupplierCard>, IEntityConfiguration
    {

        public SupplierCardConfiguration()
        {
            this.ToTable("SupplierCard", "erp_wms");
            HasKey(u => u.Id);
            Property(u => u.Id).HasColumnName("SupplierId");
            Ignore(u => u.UsePropertyNotifications);
            Property(u => u.Profile.MarketingEmailOk).HasColumnName("MarketingEmailOk");
            HasMany(i => i.PurchaseCategories)
                .WithMany(c => c.Suppliers)
                .Map(mc =>
                {
                    mc.MapLeftKey("CategoryId");
                    mc.MapRightKey("SupplierId");
                    mc.ToTable("SupplierPurchaseCategory", "erp_wms");
                });
        }


        public void AddConfiguration(ConfigurationRegistrar registrar)
        {
            registrar.Add(this);
        }
    }

 [Export(typeof(IEntityConfiguration))]
    public class SupplierProfileConfiguration
        : EntityTypeConfiguration<SupplierProfile>, IEntityConfiguration
    {

        public SupplierProfileConfiguration()
        {
            this.ToTable("SupplierCard", "erp_wms");
            Ignore(u => u.UsePropertyNotifications);
            Property(u => u.MarketingEmailOk).HasColumnName("MarketingEmailOk");
        }


        public void AddConfiguration(ConfigurationRegistrar registrar)
        {
            registrar.Add(this);
        }
    }

UPDATE:

Ok so Ive tried ignoring SupplierProfile as per suggestion that changed nothing. I then tried removing the configuration class for Supplier Profile and left

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Ignore<SupplierProfile>();
        base.OnModelCreating(modelBuilder);
    }

and that generated an error:

{"The property 'Profile' is not a declared property on type 'SupplierCard'. Verify that the property has not been explicitly excluded from the model by using the Ignore method or NotMappedAttribute data annotation. Make sure that it is a valid primitive property."} [System.InvalidOperationException]: {"The property 'Profile' is not a declared property on type 'SupplierCard'. Verify that the property has not been explicitly excluded from the model by using the Ignore method or NotMappedAttribute data annotation. Make sure that it is a valid primitive property."}

I then tried removing the

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Ignore<SupplierProfile>();
        base.OnModelCreating(modelBuilder);
    }

while leaving out the configuration class for SupplierProfile and that generates the error:

Message: "Invalid column name 'Profile_BusinessType_ContactLegalType'.\r\nInvalid column name 'Profile_BusinessType_TradingSince'.\r\nInvalid column name 'Profile_BusinessType_State'.\r\nInvalid column name 'Profile_BusinessType_UsePropertyNotifications'.\r\nInvalid column name 'MarketingEmailOk'.\r\nInvalid column name 'Profile_MarketingSmailOk'.\r\nInvalid column name 'Profile_State'.\r\nInvalid column name 'Profile_UsePropertyNotifications'.\r\nInvalid column name 'OwnerId'.\r\nInvalid column name 'State'."

So like I said, just **bumbling** along ;)

4

2 回答 2

0

After reading this I think it might have something to do with your relationship in your SupplierCard class.

public class SupplierCard : ContactCard, ISupplierCard
{
  public SupplierProfile Profile { get; protected set; }
}

I'm guessing it registering as a complex type when SupplierCard is mapped. A suggested way to fix it is to ignore it.

modelBuilder.Ignore<SupplierProfile>();

I've never run into this problem myself, so not sure if this'll help.

于 2013-08-07T23:19:15.760 回答
0

So after a lot of mucking around it turns out the underlying problem is a bug in Entity Framework 5. This bug has been fixed in EF6 beta. All other errors were in fact just masking this underlying error.

The following explaination is not terribly good as I dont fully understand it myself. Short answer is: Use EF6 or otherwise modify EF5 source code.

Turns out that if you have a class in assembly B, that has a property of a type of enum defined in Assembly A, EF5 gets confused and thinks the enum is missing or somehow unavailable and sets about trying to generate the type itself.

So I had:

  • Assembly A containing enum type AA.
  • Assembly B referencing Assembly A so a contained class BB could have a property of type AA.
  • An EF5 data layer Assembly referencing both Assembly A & B.
  • An EF5 configuration layer Assembly referencing both Assembly A & B.

And it failed.

But if I "simply" move enum type AA into Assembly B then everything works. This is of course is completely useless because then I set up all kinds of dependencies on Assembly B for any Assembly that has a member who needs an enum AA. But that is the test.

To top it off there also appears to be some particular set of circumstances in which everything I just said does not apply due to the order assemblies are loaded at runtime. The order of this loading cannot be forced i.e. it's non-determinant so it's pot luck.

于 2013-08-13T02:02:11.417 回答