Can I load SimpleMembership classes into EntityFramework? - c#

I've been trying to load the standard ASP.NET SimpleMembership (SM) classes into my EntityFramework (EF) model, but keep running into a few brick walls. I want to use the UserProfile table as a class in my model to bind applications to certain users, then let an admin decide which user can see/edit specific applications.
The way I'm doing it now is running the EF-generated .sql over the .mdf file ASP attaches to the DB at runtime. Then run 'Update Model from Database' in EF. The result is the following pic:
The User class should be replaced with UserProfile (and UserType by Roles), but this won't run because of ambiguity between the EF UserProfile and the SM UserProfile. ASP's internal code can't seem to handle that:
The mapping of CLR type to EDM type is ambiguous because multiple CLR
types match the EDM type 'UserProfile'
I've tried renaming the UserProfile entity to something like aspnet_UserProfile, but it results in EF not being able to find the corresponding table (because that's still named UserProfile and it should because that's where SM reads).
Is this even possible? Or am I approaching this from the wrong angle?
Small side-question: why is the .mdf a standard MVC project uses so small compared to the classes the aspnet_regsql.exe tool adds?

EF doesn't allow you to have class that differs only by namespace. You can rename the entity as you did but change the mapping so the table name is still UserProfile.
See mapping details window. Another option is to let the mapping unchanged (after changing entity name so you have a table name different from 'UserProfile') and specify it in the initialisation of your identity provider WebSecurity.InitializeDatabaseConnection.
The table you see are simplified and allows better integration than the old way to do SQL Membership (aspnet_regsql). If you want more information about new identity and background on membership, see the Introduction to ASP.NET Identity

Note that the Simple Memebership provider comes with :
It was hard to persist membership system data in a non-relational
store.
You can't use it with OWIN.
It doesn't work well with existing ASP.NET Membership providers, and
it's not extensible.
Entity Framework uses only class names to identify the type mapped in EDMX and namespaces are ignored - it is a convention to allow mapping classes from different namespaces to single model. From your description, it seems that you would have two same named entities and because of the reason I mentioned above, it throws the error.
But you can name your classes in BLL differently (You have used classes with the same name - EF uses only class names to identify the type mapped in EDMX (namespaces are ignored)) and rename the entities as the workaround.

Related

EF Core : how to re-scaffold without losing custom changes?

There is a WPF application that is currently transitioning from Entity Framework 6 to Entity Framework Core 5 (database provider is Oracle, the application uses .NET 5 so EF Core 6 isn't possible currently).
There is one big issue to solve: two scaffolded data types weren't correct (from bool to byte and from bool to int). I changed those types manually. If I now re-scaffold, those changes will be removed for sure.
So my question: is there any possibility to re-scaffold (using the -force parameter) without losing the manually changed types OR is there any possibility to override the types which will be generated by scaffolding?
In Entity Framework 6, we used custom data type on EDMX creation to solve this issue:
What I tried and missed: creating a partial class with the same class name (but different file name) which only contained my changes.
The reason why I'm not using migrations is that I use different database stages.
Thanks for your help!
What I tried and missed: creating a partial class with the same class name (but different file name) which only contained my changes.
This will work with the caveat that when the db is re-scaffed the new entities will have the same props appear again (but wrongly typed) and if they're also defined in your partial class you'll get a compile error due to two members having the same name
I'd recommend you install EFCore Power Tools extension and use it to scaff (Reverse Engineer) because there's a section of the "wizard" where it asks you which things you want to scaff and you can untick those columns in the DB to omit them from the models. If they take part in some relationship or have atypical properties meaning they get special attention in the fluent config then you might have to consider an alternative strategy that I use a lot; scaff to a different folder and then run a diff tool to help you merge changes into the main model, then delete the new scaff set.
I leave myself comments in the context that "is the main one", such as "//do not remove this enum column config during context merge", having set up some fluent blah that I know will not be present in the new scaffing
EFCPT does also have some abilities to customize the generated code but I don't know if it goes as far as entirely rewriting parts (I've never looked). It's open source so you can also look at modifying it to meet your needs

Do I need entity data model in OnModelCreating for runtime DB context?

So, I'm using EF DbContexts in the following way. One AppDbContext is an abstract class derived from DbContext, it contains my DbSets and is used as a type to inject into services. Its "implementation" is like AppDbContextMySql, which is self-explanatory - it's derived from AppDbContext and handles the connection to the actual DB. There can be several such abstract/implementation pairs to separate the data tables, but usually, all of them point to the same actual DB instance.
Then I need to migrate it all, so I add a MigrationDbContext implementing all the datasets and all the entity configurations needed, namely composite primary keys which can only be configured in OnModelCreating override.
The question is, if I already have the data model configuration in MigrationDbContext, have applied the migration successfully to the DB, and it's DB's job to handle keys and indexes anyway, do I need to have the model configuration in my actually consumed AppDbContext or AppDbContextMySql? In other words, is the model only used to generate migration scripts, or is it also needed at runtime to help EF handle the data in any way?
The short answer is yes, the model is definitely needed in all the cases.
Generating migrations from it is just one of the possible usages, and for sure not the primary - migrations are optional feature which may not be used at all.
The primary purpose of the model is to provide the mappings between the data (objects, properties, navigations) and the storage (database tables, columns and relationships). It is basically the M part of the ORM (Object Relational Mapper) what EF Core is.
It controls all EF Core runtime behaviors - LINQ queries, change tracking, CUD etc. Like what is the associated table/column name, what is the PK/FK property/column, what is the cascade delete behavior, what is the cardinality of the relationship and many others.
The way you asked the question makes me think you are assuming that the model is used just for migrations while at runtime EF Core takes that metadata information from the actual database. That's not the case. For EF Core the database is whatever you told them in the model configuration. Whether the physical database is in sync (correctly mapped) is not checked at all. That's why people start getting errors for non exiting columns in their queries when they screw-up some fluent configuration, or more importantly - do not include such.
Which is the main drawback of using separate (a.k.a. "bounded") contexts for a single database. Because having a DbSet type property in the derived context is not the only way the entity is included in the model. In fact typed DbSet properties are just for convenience and are nothing more than shortcut to the DbContext.Set<T>() method. A common (a sort of hidden) method of including entity in the model is when it is referred (either directly or via collection) by another already included entity. And all that recursively.
And when the entity is included in the model, it needs the associated fluent configuration regardless of the concrete context class. Same for referenced entities, and their references etc.
So I don't really see the benefits of "bounded" context classes - they probably work for simple self containing object set with no relations to other (and vice versa), but can easily be broken by this automatic entity inclusion mechanism.
For reference, see Including types in the model and Creating and configuring a model.

ASP.NET MVC - Using Identity with existing, modified AspNetUsers table

At my company the DBA updates our SQL Server tables to add columns, etc and when pushing these changes to prod. In my scenario we have an existing AspNetUsers table and other Identity-related tables. This existing AspNetUsers table has additional columns added (FirstName, LastName, Joined date) and the id column was changed to an int.
I'm writing a new MVC Web Api (VS 2013) on top of this existing database and I started with the default Web Api template that uses Identity which I really like. I can't use Code-First since the tables already exist and already have these additional fields. I will not and cannot have my code update the DB through Nuget, and I'm not responsible for creating DB scripts either.
My question is: How can I have my code work with an existing AspNetUsers table that has additional fields that I'll need to capture when registering the user? I've added the new properties to the IdentityModel.cs inside of ApplicationUser : Identity User. I've also added these fields to my AccountController's Register method and the AccountBindingModel's RegisterBindingModel class. The error I'm getting when registering the user is "Mapping and metadata information could not be found for EntityType Phoenix.WebAPI.Models.ApplicationUser" and I don't know how to approach this since I'm not allowed to touch the DB and don't want to use Code-First.
Well, let's see:
At my company the DBA updates our SQL Server tables to add columns
As far as I understand about IT positions, an DBA should not do that. Database modelling is a job for an Analyst.
I can't use Code-First since the tables already exist and already have
these additional fields
That is not right. You can use Code-First in a existing database, it also works way better than EDMX. EDMX has been discontinued in EF7.
However, if you really don't want to use Code-First, take a look at this library https://github.com/kriasoft/AspNet.Identity it might be helpful.
You can try to use Fluent API to map your entities to database tables.
fluent api

Adding custom columns to ASP.NET Identity

Trying to grasp the big picture here. This is a Web Forms project using Identity + EF for user management. The default project contains IdentityModels file which suggests that I should add custom properties to ApplicationUser class and then use migrations to update my database. I did that and the database was generated/updated. So far so good.
Now I add a new EDMX to my project and import all my DB tables into it. This obviously brings in Identity tables into the diagram as well, which is good because I'll be adding my business domain tables and linking them to Identity tables through the model and then use migrations to update my database. Here are the questions and problems I face:
Am I using Code-First or Model-First, or a mix of both (Does such a mix work)?
Do I have more than one model in my project, namely the default Models file and the one generated by EDMX?
If I have two models, which of the model classes correspond to AspnetUsers table; the default ApplicationUser class or the AspNetUser class generated by the EDMX? I mean which of these classes will be used by migrations to update my table's structure?
Adding new properties to my ApplicationUser class doesn't seem to have any effect when I run Add-Migration and Update-database commands. It generates empty Up() and Down() functions.
Adding a new property to an EDMX entity and then trying to send it to the database through migrations throws error saying that the new property doesn't have a mapping column. Now that's obvious I know, but then how does Model-First approach send changes to the DB?
I know these are more than one questions, but they are tightly related and anyone trying to get a start will most probably face all of them, so I've gathered them in one place for future readers.
In my understanding using both EF Code-First and Model-First can add a burden of keeping them in sync. You may want to check the following sample project which uses only DbFirst approach:
https://github.com/kriasoft/AspNet-Server-Template
OK. After working with the project for a few days, I have figured out a few things that might be helpful for future readers:
As #Konstantin said, as a general rule, you should not use both code-first and model-first approaches in the same project. Personally I prefer database-first over both of them, i.e. create a database design and then import it into my EDMX model. I can then make changes to my DB design later and use "Update Model from Database..." command to refresh my model.
AFAIK, migrations cannot currently be used with EDMX models. These only work with code-first approach.
ASP.NET Identity will automatically create all required tables in your database when your website runs for the first time. You simply need to correct the connection string in your web.config file.
You should generally avoid bringing in Identity tables into your EDMX, but if you really need to do that, do not make changes to these entities through EDMX. Simply use ApplicationUser class in IdentityModels file to add custom properties to your user class.

missing Navigation property in auto-generated entity class

I am moving my first steps in the Entity Framework 4.0, and I am currently facing an annoying issue.
The authentication/authorization process of my application is based on the standard ASP.NET membership provider, in other words the database is the well-known ASPNETDB.MDF. In this database there are - amongst others - the tables aspnet_Users and aspnet_Roles, which are linked together by the table aspnet_UsersInRoles.
I generated a new "ADO.NET Entity Data Model", I selected Generate from Database, I provided all the necessary parameters, and the wizard generated for me the relative .EDMX file. I named this "SecurityModel". In the aspnet_User entity I can see there is a navigation property that should retrieve all linked Roles, and viceversa.
At this point I added a new "Domain Service", in my case SecurityDomainService.
When I was asked, I selected the SecurityModel, and all the tables it contains.
Even in this case the wizard generated the SecurityDomainService for me.
Apparently no problems at all. However, I realized that in the entity aspnet_User I have all navigation properties (Membership, Profile, Applications, etc.) but Roles.
I read somewhere that EntityFramework doesnt handle many-to-many relationships. However I can see in my Entity Data Model that an Association exists between aspnet_Roles and aspnet_Users, and it is based on aspnet_UsersInRoles. I can also see in the Data Model designer the "Roles" navigation property in the User entity.
So, my question is why has not this navigation property been generated?
Thanks in advance for all your help.
Cheers,
G.
The problem here is that the aspnet_UsersInRoles table contains only the primary key fields of the tables in the many to many relationship. Entity Framework 'inlines' this table and does not represent it as an entity. Entity Framework handles this fine - it is RIA services that does not support this type of relationship.
Simply adding one extra field to the table will prevent it from being inlined and result in an aspnet_UsersInRoles being generated. This will be supported within RIA Services.
You will need to be careful modifying the aspnet schema to ensure that you do not break any of the stored procedures etc but the addition of a nullable bit column should not cause too much disruption.

Categories

Resources