I'm attempting to use the Simple Membership Provider with MVC 4 as "by the book" as possible. Here is the current scenario:
-- I've been using Jon Galloway's blog post on the topic here.
1) I'm aware this thing is wired via Entity Framework. I did notice, however, that when I added properties to the UserProfile class, they didn't appear in the table automatically when it was generated. Is this due to the database already being generated (tables were not present)? I manually added the fields and it was functional, but would be nice to know the "gotchas" that would result in the fields not being automatically created.
2) As far as the roles, it seems that it is geared primarily towards a global permission type thing (ie user is a User, Admin, etc.). In the event that you want to make it handle at a project level (ie admin for project1, user for project2), what modifications need to be made?
etc) Is there an article that really goes into detail in regards to best practices on how to extend it?
1)I find the UserProfile table part of Simple Membership a little complicated (in a good way), but it has worked great for my apps.
The convention for Simple Membership is to create a UserProfile table named "UserProfile" with two fields, UserId and UserName. You can configure a different table name or different UserId and UserName field names for the UserProfile by modifying the WebSecurity.InitializeDatabaseConnection() line in Filters/InitializeSimpleMembershipAttribute.cs. You can create a UserProfile table with additional fields and it will be used by Simple Membership if Simple Membership finds that table the first time it runs. Under the default configuration, the first time your app runs SimpleMembership will create the database tables including whatever UserProfile table details specified in Filters/InitializeSimpleMembershipAttribute.cs.
So, the trick is to create the UserProfile table you want (including all the fields you want in that table) before the first call to Simple Membership. This could be created by EF Migrations or created by a database script or even created manually in SSMS.
If you want to dig into the Simple Membership code, see http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/5cb74eb3b2f3#src/WebMatrix.WebData/WebSecurity.cs and http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/5cb74eb3b2f3#src/WebMatrix.WebData/SimpleMembershipProvider.cs.
2)I agree with your point about roles and global permissions. Maybe you could use AddUsersToRoles and RemoveUsersFromRoles (in http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/5cb74eb3b2f3#src/WebMatrix.WebData/SimpleRoleProvider.cs) to modify a user's roles at login according to the project they use.
etc)I don't know of a good article on extending Simple Membership, but in principle Simple Membership extends the Extended Membership Provider which extends ASP.NET Membership Provider. You should be able to jump in at an appropriate point.
EDIT in response to Robert's comment:
As a direct answer to why Entity Framework did not create the columns added to the UserProfile class, this happens when the UserProfile table was already created by the SimpeMembership initialization before the app-specific table creation ran. The reason is SimpleMembership has an inbuilt definition of the UserProfile table that is used anytime SimpleMembership creates that table. The timing of the UserProfile table creation is important, so there is a need to make sure the app-specific tables are created before the SimpleMembership initialization runs.
Related
I've read through a bunch of tutorials to the best of my ability, but I'm still stumped on how to handle my current application. I just can't quite grasp it.
My application is simply a read-only directory that lists employees by their company, department, or sorted in alphabetical order.
I am pulling down JSON data in the form of:
Employee
Company name
Department name
First name
Last name
Job title
Phone number
Company
Company name
Department
Company name
Department name
As you can see, the information here is pretty redundant. I do not have control over the API and it will remain structured this way. I should also add that not every employee has a department, and not every company has departments.
I need to store this data, so that it persists. I have chosen Core Data to do this (which I'm assuming was the right move), but I do not know how to structure the model in this instance. I should add that I'm very new to databases.
This leads me to some questions:
Every example I've seen online uses relationships so that the information can be updated appropriately upon deletion of an object - this will not be the case here since this is read-only. Do I even need relationships for this case then? These 3 sets of objects are obviously related, so I am just assuming that I should structure it this way. If it is still advised to create relationships, then what do I gain out of creating those relationships in a read-only application? (For instance, does it make searching my data easier and cleaner? etc.)
The tutorials I've looked at don't seem to have all of this redundant data. As you can see, "company name" appears as a property in each set of objects. If it would be advised that I create relationships amongst my entities (which are Employee, Company, Department), can someone show me how this should look so that I may get an idea of what to do? (This is of course assuming that I should use relationships in my model.)
And I would imagine that this would be the set of rules:
Each company has many or no departments
Each department has 1 or many employees
Each employee has 1 company and 1 (or no) department
Please let me know if I'm on the right track here. If you need clarification, I will try my best.
Yes, use relationships. Make them bi-directional.
The redundant information in your feed doesn't matter, ignore it. If you received partial data it could be used to build the relationships, but you don't need to use it.
You say this data comes from an API, so it isn't read-only as far as the app is concerned. Worry more about how you're going to use the data in the app than how it comes from the server when designing your data model.
So I'm creating a database model using Entity Framework's Code First paradigm and I'm trying to create two tables (Players and Teams) that must share a uniqueness constraint regarding their primary key.
For example, I have 3 Players with Ids "1", "2" and "3" and when I try to create a Team with Id "2", the system should validate uniqueness and fail because there already exists a Player with Id "2".
Is this possible with data annotations? Both these entities share a common Interface called IParticipant if that helps!
Txs in advance lads!
The scenario you are describing here isn't really ideal. This isn't really a restriction on Entity Framework; it's more a restriction on the database stack. By default, the Id primary key is an Identity column, and SQL itself isn't really supportive of the idea of "shared" Identity columns. You can disable Identity and manage the Id properties yourself, but then Entity Framework cannot automatically build navigation properties for your entities.
The best option here is to use one single participant table, in a technique called "Table Per Hierarchy", or TPH. Entity Framework can manage the single table using an internal discriminator column. Shared properties can be put into the base class, and non-shared properties can be put on the individual classes, which Entity Framework will composite into a single large table in the DB. The main drawback to this strategy is that columns for non-shared properties will automatically be nullable in the database. This article describes this scenario very well.
The more I try to come up with a solution, I realize that this is an example of the XY Problem. There is not really a good solution to this question, because this question is already a proposed solution. There is a problem here that has led you to create an Interface which you suggest requires the entities which are using the interface to have a unique Id. This really sounds like an issue with the design of the Interface itself, as Interfaces should be agnostic to the entity they are applied to. Perhaps providing some code and showing what your problem actually is would be helpful, since the proposed solution you are asking how to implement here isn't really practical.
I'm using ASP.NET MVC3 with Entity Framework 4.
I am using the Unit Of Work + Generic Repository pattern.
I searched for similar question everywhere, I see that many people have my problem, but still can't find a good and practical solution.
We have a multi-tenant database.
Imagine a database with a similar structure:
customers
groups, associated to a customer
users, associated to one or many groups
And then, for each customer we have
resources, associated to one or many groups, and linked between each other with foreign keys, many-to-many relationships and so on
So, when a user logs in, he is associated to one or many groups, and he needs to have access to the parent and child resources associated to that groups.
Now the problem is:
I implemented a sort of pre-filtering with a .Where() clause into the unit of work, in the repositories, based on the id of the logged in user.
And this is working.
The pre-filtering I did on the repositories is working fine, but of course it works only if you access directly the repository of the sources of TYPE A or TYPE B or TYPE C and so on.
But a resource is linked to other resources with many-to-many tables and foreign keys.
So, it happens that sometimes a resource belongs to a group to which the user has access, but sometimes the resources linked to this resource belong to a group to which the user does not have access.
If I traverse the navigation properties of the "parent" resource, the user can access all the linked resources, even the one belonging to other groups.
So, if you are starting from a TYPE A resource, and traverse the navigation properties to reach the TYPE B and TYPE C resources, they are not filtered.
If you access the TYPE B and TYPE C repositories, they are filtered.
Now my filters, as I said before, are in the Unit Of Work class, but I tried to move them into a custom DBContext, applying the filters directly into the DBSet, but nothing changes:
It seems that EF is accessing directly the database to build the navigation properties, thus not using the other repositories or the other DBSet, avoiding the prefilter.
What can we do?
I see that NHibernate has Global Filters that could accomplish my task, so I'm evaluating a migration from EF to NH.
I see that many other people is asking for .Include() filters, thus disabling lazy loading.
Thank you.
I can provide some piece of code if needed, but I hope I explained my problem correctly.
Thank you i.a.
Best Regards,
Marco
I saw a solution with mapping to views and stored procedures, but I'm not sure how hard it was in development and maintanace. In short, it is possible to map EF model to views, where data will be filtered; in this solution each user have own database credentials.
Im currently working in a team that uses EF as the ORM of choice.
We have a common project that contains many EDMX files.
The reason for this is to keep the EDMX files small and manageable while also allowing them to focus on a conceptual set of tables on the database.
Eg
Orders.edmx
Users.edmx
Trades.edmx
These all point to a different set of tables on the same db.
I now need to add the user table to the Trade.edmx file. Since the user table is already in the user.edmx file, this creates the same User type twice under a different namespace which means I would need 2 UserRepository objects.
Common.data.trade.User
Common.data.users.User
Is there a way of avoiding 2 repository objects for the same table?
Any suggestions would be greatly appreciated
If you are using POCO generator you can update template for Trades.edmx to not generate new User class and its context template to use User class from Users namespace. EF matches POCO classes with entities in designer only by the class name (namespace is omitted) so it will work.
The disadvantage is that you have User entity in two mapping files and you must update it in both files or your application throw exception at runtime.
The reason for this problem is your architecture - at the beginning you wanted separated models but know you want to combine entities from different models. Those are contradicting requirements. Either use separated model where Trade knows only userID without any navigation property (like if it is defined in another database) or move all entities to single EDMX to support your new requirements.
Let's say, I have 2 classes in the model: User (mapped to USERS table) and PrivilegedUser (inherits User, additional info is stored in PRIVILEGEDUSERS table).
Now, I have a row in USERS (and instance of User) and need to convert that user to PrivilegedUser (i.e. to create a record in PRIVILEGEDUSERS with the same Id). Is there a way to do this without Delete/Insert?
The problem is you don't have PRIVILEGEDUSERS representation in the model, so you cannot create only that part of PrivilegedUser.
It was just an example. PrivilegedUser may have some discount or personal manager or whatever in addition to ordinary User properties. In the same time, there are other tables which need to reference users regardless of concrete User type. I've implemented it using Table-per-Type inheritance mode. In the database level it's very simple to convert users from one type to another (you just need to insert or delete record from extension table). But in EF you have only UserSet which stores both User and PrivilegedUser objects. That's why I ask is it possible to replace existing User object with PrivilegedUser keeping existing Id and without deleting record from USERS table.
No you cannot.
As explained by this article, EF (3.5) does not support this feature. You must use stored procedure to accomplish this.
You need to change your world view. Your view is that you have standard users with standard privileges and super users with additional privileges. The privileges aren't enumerated, they are implicit.
The new world view is that you maintain a list of all privileges, both standard and super and then in a mapping table you create a many to many map of which users have which privileges. When a user is granted super privileges, you just add mappings for the appropriate privileges to the mapping table. You don't need a PrivilegedUser class, just a list of privileges in the User class. The privileges may be either standard or super.
It seems wrong that you have two tables representing users.
Would it not be better to have a Users table (for all users) and then a UserPrivileges table, representing what they are allowed to do? This way, no deletes/Inserts are needed, and you can reference just one table for users.
A third table can be used to represent the actual privileges.
Users
Id Username ...
UserPrivileges
UserId PrivilegeId
Privileges
Id Description
Regarding inheritance in EF take a look at this site, which explains the three different ways to use inheritance in EF.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/01/20/entity-framework-inheritance-types.aspx
As said, you cannot. Either by stored procedures or by custom insert/update query. I had similar problem, now I'm using solution that i described in this answer: https://stackoverflow.com/a/28380804/2424989