Base solution for your next web application
Open Closed

Creating a separate module outside main app #2694


User avatar
0
bilalhaidar created

Hello,

I am trying to re-do the Blog Module created by <a class="postlink" href="https://github.com/hikalkan">https://github.com/hikalkan</a> and hosted on <a class="postlink" href="https://github.com/aspnetboilerplate/sample-blog-module">https://github.com/aspnetboilerplate/sample-blog-module</a>.

I added the .Core, .Application and .Web modules. For the EntityFramework, I decided to include the Posts, Categories and Comments entities as part of the main App Db Context, as I mighit have entities from one module to be shared by another module, so this way, all modules will be using same Dbcontext.

The problem is the Blog module defines its own BlogUser and BlogRole and the exception below shows that. How to work around this?

Also, if I include those tables in main DbContext, how would Blog module be able to access the DbContext?

I got lost a bit.

I do care a lot to have my modules separate so that I can upgrade main framework files with every new release you have to benefit from bug fixes and new features.

I appreciate your assistance. Thank

PM> Add-Migration "Added_Blog_Tables"
System.InvalidOperationException: The entity types 'BlogUser' and 'User' cannot share table 'AbpUsers' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.
   at System.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration.UpdateColumnNamesForTableSharing(DbDatabaseMapping databaseMapping, EntityType entityType, EntityType toTable, MappingFragment fragment)
   at System.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration.FindOrCreateTargetTable(DbDatabaseMapping databaseMapping, MappingFragment fragment, EntityType entityType, EntityType fromTable, Boolean& isTableSharing)
   at System.Data.Entity.ModelConfiguration.Configuration.Mapping.EntityMappingConfiguration.Configure(DbDatabaseMapping databaseMapping, ICollection`1 entitySets, DbProviderManifest providerManifest, EntityType entityType, EntityTypeMapping& entityTypeMapping, Boolean isMappingAnyInheritedProperty, Int32 configurationIndex, Int32 configurationCount, IDictionary`2 commonAnnotations)
   at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.ConfigureTablesAndConditions(EntityTypeMapping entityTypeMapping, DbDatabaseMapping databaseMapping, ICollection`1 entitySets, DbProviderManifest providerManifest)
   at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntityTypes(DbDatabaseMapping databaseMapping, ICollection`1 entitySets, DbProviderManifest providerManifest)
   at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(DbDatabaseMapping databaseMapping, DbProviderManifest providerManifest)
   at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
   at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.InternalContext.ForceOSpaceLoadingForKnownEntityTypes()
   at System.Data.Entity.DbContext.System.Data.Entity.Infrastructure.IObjectContextAdapter.get_ObjectContext()
   at Abp.EntityFramework.AbpDbContext.RegisterToChanges() in D:\Halil\Github\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\AbpDbContext.cs:line 141
   at Abp.Zero.EntityFramework.AbpZeroDbContext`3..ctor(String nameOrConnectionString) in D:\Halil\Github\module-zero\src\Abp.Zero.EntityFramework\Zero\EntityFramework\AbpZeroDbContext.cs:line 66
   at MainApp.EntityFramework.MainAppDbContext..ctor() in D:\Workspace\MainApp\app\MainApp.EntityFramework\EntityFramework\MainAppDbContext.cs:line 41
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Data.Entity.Infrastructure.DbContextInfo.CreateInstance()
   at System.Data.Entity.Infrastructure.DbContextInfo..ctor(Type contextType, DbProviderInfo modelProviderInfo, AppConfig config, DbConnectionInfo connectionInfo, Func`1 resolver)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
   at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
   at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
   at System.Data.Entity.Migrations.AddMigrationCommand.&lt;&gt;c__DisplayClass2.&lt;.ctor&gt;b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

14 Answer(s)
  • User Avatar
    0
    bilalhaidar created

    Ok, I removed the folder Auth from the Blog.Core module and added a reference to the MainApp.Core so that both use the same User, Role, etc.

    Now, when I run the application I get this exception. I went back to check the code for the blog module, there was an attribute on the Blog DbContext as follows:

    [AutoRepositoryTypes(
            typeof(ISampleBlogRepository<>),
            typeof(ISampleBlogRepository<,>),
            typeof(SampleBlogRepositoryBase<>),
            typeof(SampleBlogRepositoryBase<,>)
            )]
        public class SampleBlogDbContext : AbpZeroDbContext<BlogTenant, BlogRole, BlogUser>
    

    Maybe Framework has changed a lot since that blog module was created. But really, why is it that difficult to create a custom module and make the application moduler?

    "Can't create component 'MainApp.Blog.Posts.PostAppService' as it has dependencies to be satisfied.
    ↵
    ↵'MainApp.Blog.Posts.PostAppService' is waiting for the following dependencies:
    ↵- Service 'MainApp.Blog.Domain.Repositories.ISampleBlogRepository`1[[MainApp.Blog.Posts.Post, MainApp.Blog.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' which was not registered.
    ↵"
    
  • User Avatar
    0
    bilalhaidar created

    Now, when I re-use Blog.EntityFramework in a sense I set SetInitializer(null) so that only 1 DbContext creates tables, the rest will just use the existing tables.

    I then get this exception below.

    So dealing with separate modules is full of exceptions and spending lots of hours to make this work.

    Found more than one concrete type for given DbContext Type (Abp.Zero.EntityFramework.AbpZeroCommonDbContext`2[MainApp.Authorization.Roles.Role,MainApp.Authorization.Users.User]) define MultiTenancySideAttribute with Host. Found types: MainApp.EntityFramework.MainAppDbContext, MainApp.EntityFramework, Version=3.1.0.0, Culture=neutral, PublicKeyToken=null, MainApp.Blog.EntityFramework.MainAppBlogDbContext, MainApp.Blog.EntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
    
  • User Avatar
    0
    JeffMH created

    You don't need BlogTenant, BlogRole, BlogUser in AspNetZero. Remember, Hikalkan implemented that example on top of Boilerplate, not AspNetZero. AspNetZero already implements those items with the User and Role objects. Remember, AspNetZero is an implementation of Boilerplate, so it's a best practice implementation of that Idea. So, you just have to keep that in mind when you see examples on Boilerplate.

    So let's take this from his example:

    [Table("BlgPosts")]
        public class Post : FullAuditedEntity<int, BlogUser>
        {
            public const int MaxTitleLength = 128;
    

    In AspNetZero, you need to inherit just from FullAuditedEntity. Don't reference BlogUser.

    <a class="postlink" href="https://aspnetzero.com/Documents/Developing-Step-By-Step">https://aspnetzero.com/Documents/Develo ... ep-By-Step</a> (Pick your flavor from list)

    That step by step guide shows this when it talks about creating the People entity.

    Hope that points you in the right direction.

  • User Avatar
    0
    JeffMH created

    Not sure what your goal is on the EF side. Maybe post the project you are trying to code and someone can help.

    Also, I have never had to implement AutoRepositoryTypes within AspNetZero. Not sure what that attribute is for. Someone else might need to chime in here and explain that one.

    My suggestion is do the AspNetZero walk through, and maybe avoid looking at anything on the Boilerplate side to learn AspNetZero. Maybe that's causing some confusion.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @drcgreece,

    Can you share your Blog module's DbContext definition ?

    Thanks.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I have deleted your last post in this topic because sharing source code here is against license rules. Can you also delete files from dropbox as well ?

    Please share only your DbContext class's content here or you can send the whole project via email.

    Thanks.

  • User Avatar
    0
    bilalhaidar created

    Oh sorry I didn't know that.

    I emailed the code to your email. Let me know if you received it pls.

    Regards Bilal

  • User Avatar
    0
    JeffMH created

    <cite>ismcagdas: </cite> Hi,

    I have deleted your last post in this topic because sharing source code here is against license rules. Can you also delete files from dropbox as well ?

    Please share only your DbContext class's content here or you can send the whole project via email.

    Thanks.

    Sorry as well. I didn't realize that when I asked him to post it.

  • User Avatar
    0
    ismcagdas created
    Support Team

    No problem, I thought I was the one asking for it :)

  • User Avatar
    0
    bilalhaidar created

    Hi Ismail, you have the code in your inbox :-) Whenever you have time to check it, I appreciate it.

    Bilal

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Thanks, I have the code :). I will check it as soon as possible and get back to you.

    Thanks.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @drcgreece,

    Your shared solution does not contain Blog.EntityFramework project. I think you added your entities to Main dbContext.

    I think the previous problem was causing by deriving your Blog dbContext from AbpZeroDbContext, it should be AbpDbContext.

  • User Avatar
    0
    bilalhaidar created

    That is possible! I will check it out.

    If I want to make use of UserAppService in my Blog module, i can just use either property or constructor injector for IUserAppService and then I will be able to use that?

    Thanks

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Yes, it should work.