NopCommerce 4.3 (BETA) - Fluent Migrator workflow

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
3 years ago
Great answer spincel,
Thanks a lot for the detailed explanation, you are great!

I support SuperNopCommerce opinion that this can be really helpful for other developers. I hope that Nop team will make some changes and clarify the new ideas and approaches so it can be easier for the developers.
3 years ago
spincel wrote:


Now what about the enum StatusEnum that I have above? What if I want to map it to different type in the database? In order to do that, you would have to include a NopEntityBuilder mapping class similar to the previous NopEntityTypeConfiguration.

public class NewEntityMappingBuilder : NopEntityBuilder<NewEntity>
{
    public override void MapEntity(CreateTableExpressionBuilder table)
    {
        table.WithColumn(NameCompatibilityManager.GetColumnName(typeof(NewEntity), nameof(NewEntity.Status))).AsInt32(); // Map enum to database integer type
    }
}



Sorry for the dumb question( it is referenced to this specific quoted part of your post):
But what other option do we have? I mean what other choice we have to map an Enum?
And what will happen if we do not specify such an explicit mapping with the builder? Will linq2db manage to map it by it self?

Thanks and again sorry if my question is inadequate!

Regards,
Kris
3 years ago
KrisPetkov wrote:

Sorry for the dumb question( it is referenced to this specific quoted part of your post):
But what other option do we have? I mean what other choice we have to map an Enum?
And what will happen if we do not specify such an explicit mapping with the builder? Will linq2db manage to map it by it self?

Thanks and again sorry if my question is inadequate!

Regards,
Kris

At the moment, I have not found alternative for it. This is basically what we have done previously in the last version, albeit a little different.

For example, this is what I have in my 4.2 version of my plugin

public class EntityMap : NopEntityTypeConfiguration<Entity>
{
    public override void Configure(EntityTypeBuilder<Entity> builder)
    {
        builder.ToTable("TableName");
        builder.HasKey(m => m.Id);
        builder.Property(m => m.PropertyName); // String property
        base.Configure(builder);
    }
}

And this is the equivalent in 4.3:

public class EntityMappingBuilder : NopEntityBuilder<Entity>
{
    public override void MapEntity(CreateTableExpressionBuilder table)
    {
        table
            .InSchema("TableName")
            .WithColumn("Id").AsInt32().PrimaryKey()
            .WithColumn(NameCompatibilityManager.GetColumnName(typeof(Entity), nameof(Entity.PropertyName))).AsString();
    }
}


It is not required to have this as Nop will try automatically determine the mapping type using the FluentMigrator and linq2db based on the entity object. However, if you want to make sure your entity property types are matching the types in the database or if you want to have custom types instead, I suggest to use it.
Also, I forgot to mention one thing and that is you do not need to specify the mapping for everything. Let's say the entity contains 4 properties and 1 of that is a custom type, you can let Nop handles the other 3 and just specify told the mapping to map the one that has the custom type.

About the document, I wish I could contribute to it but kinds of busy at the moment, so that is the limit factor. Hopefully, I can do that in the near future. Also, I think Nop team could have add more specific scenarios and document since this is only my experience so far with the latest version so there could be some issues. Some of the documents are pretty barebone and when I started working with plugin development, I also struggled quite some times and I had to dig into the codebase heavily to see what is going on there.
3 years ago
I thought I would add my Experiences with Fluent Migrator and Nop 4.3: -

1. Take a look at Nop.Data Migrations Folder, this should give you a good overview of how the installer takes "SchemaMigration.cs" as well and FK's and Indexes and lays out the initial DB.
2. For a plugin, pretty easy. Add you migration in the Plugin and nop will do everything else for you.
2. To extend the core product add you Domain class(es) in the Core and relevent Migration(s) in the Nop.Data project (best spot is in the Migrations folder of course). Your install will pick it up, if you have an existing install and DB you want to "Upgrade" with your new Migration then temporarily remove the "SchemaMigration.cs" from the Data project and run the following code from anywhere (for example in your Home Controller) remember to remove the code though after your DB is good to go and put the SchemaMigration.cs back into the build!

  
var migrationManager = EngineContext.Current.Resolve<IMigrationManager>();
migrationManager.ApplyUpMigrations();
2 years ago
Ayoub.rziki1 wrote:
hi,

please can you help me !!

i want to make a foreign key between two tables at not dbo schema but the secondary table point to dbo and make me that error : Setup failed: An error occured executing the following sql: ALTER TABLE [Core].[Activity] ADD CONSTRAINT [FK_Activity_StatusId_Status_Id] FOREIGN KEY ([StatusId]) REFERENCES [dbo].[Status] ([Id]) ON DELETE CASCADE The error was Foreign key 'FK_Activity_StatusId_Status_Id' references invalid table 'dbo.Status'. Could not create constraint or index. See previous errors.

thats my code : table.InSchema("Core")

            .WithColumn(nameof(Core.Domain.Activity.Activity.StatusId)).AsInt32().ForeignKey<Core.Domain.Status.Status>().OnDelete(Rule.None)
            .WithColumn(nameof(Core.Domain.Activity.Activity.ActivityTypeId)).AsInt32().ForeignKey<Core.Domain.Activity.ActivityType>().OnDelete(Rule.None)
            .WithColumn(nameof(Core.Domain.Activity.Activity.ActivityImage)).AsString()
            .WithColumn(nameof(Core.Domain.Activity.Activity.ActivityDate)).AsString(10)
            .WithColumn(nameof(Core.Domain.Activity.Activity.ActivityTime)).AsString(8)
            .WithColumn(nameof(Core.Domain.Activity.Activity.ActivityName)).AsString(50)
            .WithColumn(nameof(Core.Domain.Activity.Activity.ActivityLocation)).AsString(30)
            .WithColumn(nameof(Core.Domain.Activity.Activity.UserCreate)).AsString(68)
            .WithColumn(nameof(Core.Domain.Activity.Activity.UserModif)).AsString(68)
            .WithColumn(nameof(Core.Domain.Activity.Activity.DateCreate)).AsDateTime()
            .WithColumn(nameof(Core.Domain.Activity.Activity.DateModif)).AsDateTime();


So if I understand correctly, you have 2 tables (Activity and Status) both under "Core" schema, but the mapping does not properly figure the Status table schema. Is that right?

Also, I believe you are on 4.4 branch since Nop added ForeignKey<TPrimary> extension to the FluentMigratorExtensions.

If so, you can use the overload version of ForeinKey:
ForeignKey(string foreignKeyName, string primaryTableSchema, string primaryTableName, string primaryColumnName)
from FluentMigrator builder instead of ForeignKey<TPrimary> here.

If you look at the source code for ForeignKey extension from Nop, it just calls
column.Indexed().ForeignKey(primaryTableName, primaryColumnName).OnDelete(onDelete);


So to replicate the similar behavior, instead of
.WithColumn(nameof(Core.Domain.Activity.Activity.StatusId)).AsInt32().ForeignKey<Core.Domain.Status.Status>().OnDelete(Rule.None)

try this:

.WithColumn(nameof(Core.Domain.Activity.Activity.StatusId)).AsInt32().Indexed().ForeignKey("FK_Activity_StatusId_Status_Id", "Core", nameof(Core.Domain.Status),  nameof(BaseEntity.Id)).OnDelete(Rule.None);
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.