I kind of figured maybe you hadn't put two and two together but we've talked before or I talked to someone at 4Matrix. :) You can always let me know if you need help but I also don't mind answering questions on here. I love answering questions when I know the answer I just don't get a ton of time for it all the time.
Yea, that's what the interface was helping with. Register the Interface with the container in the Initialize method of the Module in the EFCore project.
Configuration.ReplaceService<ITenantDbMigrator, AbpZeroTenantDbMigrator>(DependencyLifeStyle.Transient);
Then yes, inject that into the TenantManager and you can call your migrator(s) from there. In my TenantManager, I just changed the definition of the variable already defined in the class:
private readonly ITenantDbMigrator _abpZeroDbMigrator;
Then the code itself in the create didn't change.
Winform programming isn't super simple either. It takes a bit to learn the ins / outs of how the framework tackles certain things and then gets easier. These kind of things are a one time setup, then you are off to the races. It's all 1's and 0's right :)
So, I don't have a ton of time to or this might be a bit more detailed. But if this doesn't make sense just reply and I will try and fill in the gaps for you.
Basically you need to implement seperated DbMigrator classes in the EFCore project. Here is the one that comes with the framework....
public class AbpZeroDbMigrator : AbpZeroDbMigrator<AbpZeroTemplateDbContext>
Basically, we have seperate Tenant databases in our system and in order to migrate the tenant that has a seperate context, create as many of these classes as you have DB Contexts.
For Ours:
public class AbpZeroTenantDbMigrator : AbpZeroDbMigrator<TenantDbContext>, ITenantDbMigrator
The code for these is blank, just need a class to type the appopriate context class. I Use the interface ITenantDbMigrator to seperately identify the migrators and it helps when you inject them into managers. Then, in the TenantManager, on the create tenant, I modify the code in there to migrate using the ITenantDbMigrator and not the default one.
In Short, I created a seperate Factory, Configurer, Context, and Migrator for each of my different context classes. Also modified the Migrator console application to use the appropriate migrator when migrating hosts / tenants.
Hopefully that points you in the right direction.
@4Matrix ... One thing you could do is modify the login page to have a pre-step to "enter email address" step. Then click Next. When you click next, you could do the tenant lookup and then do any logic you needed to set the tenant Id, then do the login process with Open ID and Azure AD / show password field, etc. Lots of sites are doing this now in order to know if the user is password user or a 3rd party login user.
For Azure AD, you def want to use Open ID IMO. I thought the "Microsoft" login was just for personal accounts? Maybe I am wrong about that and you can make it work but I can say for certainty that Open ID works great.
We are using the multi-tenant Open ID setup with Azure AD using each of the tenants Azure AD setup and it's working out great for us. We also modified the login process to enter email address first so we would know if the user is a password user or an AD user (Think of it like employee login vs customer login). It's slightly different process than you are discussing since I know the tenant based on URL but I think adding an initial step would allow you to use Tenants like you want without having to setup anything in your Azure AD.
Just a thought. Hope your project is going good!
Even though you are using Azure SignalR, the app is still responsible for storing who is connected, so when it has to send a message to a particular user, you know how to send it. This is done with IOnlineClientManager. The default version of this uses memory Cache to store who is connected which in a scaled environment doesn't work. You have to change this to be some shared cache . I've seen a thread in here recently where someone used Azure storage for this, we use Redis for this. I copied code from someone else a long while ago that still works today. Would be happy to share the code with either of you. Sorry, I'm in the middle of a big deployment and I noticed this message and new without looking that this was probably the problem. I emailed my code to info@ and they can reply to those that need it.
It would be a nice addition to the codebase.
{ "claim": "name", "key": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" },
I added that as a claims mapping to fix the issue on my side.
@ismcagdas
Is there any update on timeline for this? We are fixing to kick off a big upgrade of our big aspnetzero project and would be nice to know how this might factor into the equation. Just general update works for me, doesn't need to be specific. I promise I won't hold it against you if you are off a bit (mostly lol) :)
Thanks
Well, hopefully that T4 template generates much more of the attributes needed so there won't be a need for the API. The system that I am using to generate it doesn't do terribly well at using data annotations so you have to use the API a little.
One last question, then you can move on with your day....do you continue to use the T4 and not do code first? If yes, then you just use Code First for the ABP entities, then tie in your own Context for the other data?
Again, appreciate the advice and help.
So, through the day to day you are right, we are not using fluent API for much of anything, but in the beginning, the generator kicks out some items in the OnModelCreating event that adds all the indexes and other model stuff that isn't easily represented in attributes. I could for the most part generate the entities in T4, then true up anything that is left in the OnModelCreating. Does that make sense? Just talking about the code that is generated within the context class.
I'll give the entities a try today and see how it goes. I very much appreciate the input and links. I will check back in once I am done.
Thanks
I thought about that as well but it seems a little hackish. Although I can't say other things I am doing don't feel the same way.
So we have to generate a couple things right, first the entities and then the context. The context needs to be generated with .net core code because the fluent API is different in core. The Entities could be generated in EF 6. I don't know, maybe I will try that tomorrow. I am already using a T4 template (ReversePocoGenerator) for EF6 in another project so I could generate entities with it, and generate the first round of Context code with the one I am using above.
Ugh, sounds fugly just saying it out loud lol.
Do you do this currently? I would be curious to know what process you follow.