Closed newacc12 closed 4 years ago
hi @newacc12
Owned Entity
has some restrictions, please share your entity code and EF configuration code.
TestVo.cs
public class TestVo
{
public string Prop1 { get; }
public string Prop2 { get; }
public TestVo(string prop1, string prop2)
{
Prop1 = prop1;
Prop2 = prop2;
}
}
ABP CODE AppUser.cs
public virtual TestVo Test { get; set; }
DbContextModelCreatingExtensions.cs
public static void ConfigureCustomUserProperties<TUser>(this EntityTypeBuilder<TUser> b)
where TUser: class, IUser
{
b.OwnsOne(typeof(TestVo), nameof(AppUser.Test));
b.Property<string>(nameof(AppUser.Test));
}
Running a update-database with the code above shows:
The navigation property 'Test' cannot be added to the entity type 'IdentityUser' because there is no corresponding CLR property on the underlying type and navigations properties cannot be added to shadow state.
Now using a plain .NET Core 3.1 Web Project with the same TestVo class with the only difference being the configuration on the DBContext class it works:
builder.Entity<MyUser>().OwnsOne(p => p.Test);
Let me know if that is sufficient. If not, I will recreate the entire example again and upload on github.
This is like the limitation of abp shared table.
Hmm... #2278 states that Inheritance hierarchies that include owned entity types are not supported
but I am not using any inheritance on my VO type. This link also states that it should work.
Is ABP doing something special behind the scenes or maybe is there a workaround for now?
Is ABP doing something special behind the scenes
Because abp is using shared table(AppUser
and IdentityUser
).
The limit of ef is navigations properties cannot be added to shadow state.
Hmm not sure what you mean by 'shared table'. I created a brand new web MVC project and I am using AppUser and IdentityUser and it just works: https://github.com/newacc12/TestOwnedTypes
Trying to the exact the same with ABP doesn't work. Maybe there is a work around for now?
@maliming I read the docs but couldn't find a reason why this wouldn't work. So I assume this is a limitation of ABP instead of EF since the example that I posted works. In that case are there any plans to look into it?
This is a limitation of the ABP shared table, and of course also related to ef core.
The documentation provides a way to Alternative Approaches
.
I suppose you all understood the problem. This is not a restriction of the ABP framework. You are adding a nagivation property to a shared table (AbpUsers table is shared between AppUser (your entity) and IdentityUser (identity module's entity)) and EF normally doesn't support such a usage. The migration document explains an approach overcome this problem, but it can not solve all the problems.
A workaround can be this: Just add Prop1 and Prop2 as normal string properties inside the ConfigureCustomUserProperties method. This will just make this fields added to the table. MigrationDbContext is only used for database migration, so no problem. On runtime, your main dbcontext is used and you can configure the TestVo as normal owned entity inside your dbcontext (right here)
To me, if I start a new abp solution, I will delete the AppUser and create a new aggregate root UserInfo. 🉑
What's the difference between AppUser and UserInfo except their names?
When I use AppUser with relationships (like AppUserInfo entity), I have some problems. https://github.com/abpframework/abp/issues/1414
UserInfo does not use shared table. Most of the time I will use IdentityUser directly, when I need some details, I can load UserInfo aggregate root from its repository.
@hikalkan Thanks for the reply. Did you have a chance to look at the code that I posted here: https://github.com/newacc12/TestOwnedTypes ?
So, in ABP:
The code that I posted:
Does that look right? If it does why Address would work when being configure like this.
What am I missing?
EDIT: NVM, I think I got it what you mean by shared table. It looks like my example is not the same as ABP. I tried your work around and it seems to work. I will play a little bit more with it. Thanks for your patience and @maliming !
Another problem: sometimes I cannot change both IdentityUser and AppUser in the same uow.
Another problem: sometimes I cannot change both IdentityUser and AppUser in the same uow.
That's expected. Use different UOWs (manage UOW manually).
Another problem: sometimes I cannot change both IdentityUser and AppUser in the same uow.
That's expected. Use different UOWs (manage UOW manually).
Maybe I need to grant roles to IdentityUser, and then set AppUser.IsAuthorized = true. (if the latter fails, the former needs to be rolled back)
In general, shared table bings more troubles.
Another problem: sometimes I cannot change both IdentityUser and AppUser in the same uow.
That's expected. Use different UOWs (manage UOW manually).
Maybe I need to grant roles to IdentityUser, and then set AppUser.IsAuthorized = true. (if the latter fails, the former needs to be rolled back)
In general, shared table bings more troubles.
Damn, I wouldn't like that. So, please bear with me as I am pretty new to ABP, the purpose of extending IdentityUser is so I can customize the user in my app (add more information and/or relationships), right? Do you mean that if I start using AppUser through my app I still have to deal with IdentityUser? Would I be able to extend the existing stores so all the code would be working with AppUser instead of IdentityUser? I am pretty sure I was able to do that with the previous version of ABP (before .NET Core)
Yes, IdentityUserManager providers some important methods, for example, setting user's email, granting roles.
but can it be extended to work with AppUsers instead? If so, wouldn't the problem that you describe go away?
I don't know if it can be realized, or maybe it has been realized, but I just don't know the usage.
When I try to add a Value Object as a owned entity on the AppUser class I get the following error:
The navigation property 'Prop1' cannot be added to the entity type 'IdentityUser' because there is no corresponding CLR property on the underlying type and navigations properties cannot be added to shadow state.
I've seen similar error messages in other posts but no solutions. I've tried using a brand new regular MVC project without ABP works perfectly. I can easily create a AppUser class, a VO class and configure as an owned entity and it just works. I also tried adding builder.Owned(); before base.OnModelCreating(builder); but it didn't change anything.
Is anyone else having this problem or it is just me?