I'm new to EF4 and haven't had any experience with it before. So, bear with me if this is very simple question.
I have my POCO entities (.tt file) in BOL, the .edmx file (EDM) in DAL and my webapp in Presentation layer. All the business logic goes to BLL layer.
Here are the references:
UI->BLL-DAL-BOL
BLL->DAL-BOL
DAL->BOL
BOL->None of my project.
1- Is my understanding of layers distinction correct? Am I in the right direction?
2- How can I use ASP.NET Membership provider with entities. Should I implement membership, persistence ignorant too and map all user tables in sql server to entities?
2- How can I add custom validation? I don't mean maxlength or valid email..., I mean something like access levels. For example I want certain users be able to modify a field (say productprice) in my website. Where should I use the User.IsInRole method? the BLL doesn't have any reference to user info. should I pass some parameters to BLL (like "bool CanChangePrice") to clarify access levels?
Wow Kamyar, just a few questions wrapped up in this one;-) I'm not sure if I'll cover all the possible ground, but here goes.
ProjectStructure
- generally your structure of projects is correct, and the references you have are correct. Some may argue that you want to separate your concerns a bit and break some of the references, but personally I find your structure workable.
As a practical matter I tend to keep my EDXM and POCOs in the same project. I just have an Entities folder that contains the EDXM and Model.Context.tt, a POCO folder for Model.tt and my Virtual POCO's (below), and a Repository folder for my repository & unit of work.
I also create a file called VirtualPOCOs which is a partial class bound to the POCOs generated by your T4's. My designs tend to be pretty tightly bound to database structure. The VirtualPOCO's give me a little flexibility to deviate from DB design in those one-off situations. Not to much goes in here, just those few very specific needs every project seems to have.
You may also want to consider a repository, table data gateway, or active record setup. All of these patterns will likely be combined with Unit of Work. There are tons of design patterns and your needs or preferences may push you to one or the other. The point here is to shield the upper layers from accessing the EF4 context directly. This way you can centralize connection & transaction management and ensure upper layers are only using POCOs and not accidentally holding on to linq-to-sql objects.
Membership Provider
There is a definitely a schism between the MembershipProvider and EF. You can, however, download the source code for the SQLMembershipProvider and convert it over to use EF. I actually did this conversion. The file is about 1500 lines long, but doesn't have a huge amount of ADO code.
What you didn't ask, but I think I should address, is whether you want to use Membership provider at all. If you're doing basic membership management and roles then the Membership, Roles, and Profile provider can save you a lot of time. For an in depth tour of the capabilities check out the series over at 4GuysFromRolla (https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx).
If your needs are more complex then, IMHO, the membership provider breaks down pretty quickly. For example, when a user registers for your site you immediately have to create rows in a handful of different tables. Well, the membership provider is registered through webconfig and uses the membership provider interface. It only accepts certain fields in the create function. So what's a boy to do? Well, you can open a larger scale transaction up in your controller, run the membership providers add user function, run your own MyCustomUserStuff(), then commit the transaction. Two reasons I find this unappealing are that I've now got transactional code seeping way up my call stack and if all I need to do is add a few extra fields I've now doubled my database calls needlessly.
I guess I just found the membership provider pretty restricting, and once got in there and made my own custom membership provider the benefits of using MS's model quickly fell away.
Validation
I think the answer here is a resounding --it depends. Are your permissions pretty static? i.e. those in the "SiteManagers" group can edit all over the site? Or are your permissions much more fine grained? Meaning SiteManagers have access to these 75 fields spread across these 22 tables, or is it more table based? Additionally, how mutable are the permissions ? Does your site admin need to be able to frequently turn access on/off or off to various fields in different tables?
I think I need to hear more on your requirements for a specific answer. Keep in mind that the more fine grained you make your permissions the more of a configuration headache the client will have understanding & managing all the permissions.
Also, what back-end are you using? Many DBA's face these decisions. One often used strategy in that world is to create a series of views where each view exposes the columns users have. For example, the EmployeesHR view would expose just those columns that HR people have access to, and the EmployeeDirectory would expose just those fields that the directory has access to.Then HR users are given permission to the HR view, but not the underlying table. Just a thought.
Anyway, hope this helps.
1- Your distinction of the layers seem correct to me.
I wouldn't reference the DAL in the UI, as in my projects, I prefer that only the middle layer access the DAL. But it's not wrong.
So you seem in the right direction.
2- To my knowledge there is no MembershipProvider that works with EF.
So in projects where we used Membership, here is what we did :
created the tables with the aspnet_regsql.exe
configure the Web.Config to use the SqlMembershiptProvider
added in the web.config ANOTHER connection string (one for Membership and one for EF)
Built the EDMX file with all tables, including the Membership ones.
In the code, a UserManager / RoleManager (BLL or DAL it depends on your architecture) get the informations using standard Membership methods. And always use the Membership objects, not EF ones. So in fact the user / roles management part is separated from the EF.
We only use the aspnet_* EF entities when there is a link between your custom tables and a Membership table (for instance, when you want to link one of your table with the aspnet_Users table to keep a reference of the user that inserted a data).
3- For the right management, I would use a BLL RightManager that would allow the UI to know if the user can change the field (so you can disable it, or prevent input), and to use this information in your validation method.
In my project I use a Right table and I associate a Right with a Role. In the RightManager provide a RequestRight(Right) method.
If your Right management is too simple to create tables, just use User.IsInRole() in your RightManager (so I would use it in BLL).
I would place the validation method in the UI if it is "basic" and in the BLL if it contains more complex rules (involving DAL access for instance).
about EF & Membership
as i know, you dont need to use any db provider instead of membership provider
but if you want, you can map membership tables in EF and create additional method to
common provider
Related
I have the following database schema (in the early stages at the moment):
Everything on the right is created by the ASP.NET Provider model. They were a bunch of automatically generated tables that were created the first time that I used the login controls.
Now, I've settled for the moment in using this schema and extending it with my own tables. I'm not looking to implement any custom Providers at the moment.
My question is, can I delete the Profiles and _MigrationHistory tables?
I'm not using the Profile Provider
I'm only using the Role and Membership Providers
Will I break the Internets if I simply get rid of the Profiles and _MigrationHistory tables?
EDIT: The Profiles Provider is disabled in web.config.
The Interwebs do not break if I delete those tables. As long as no Profile Provider is used, the tables can still be used and accessed as they normally would be. They are not regenerated and no functionality is lost. The Membership/Profile/Role Provider tables can be extended or modified (as long as constraints are kept in check) or, as I was wondering, deleted.
I use ASP.NET MVC 3 for an application which makes heavy use or Users and Roles.
To create a user and assign role(s) I use the standard process via ASP.NET Membership.
Throughout the entire app I use NHibernate for the underlying data access except the places were the default MembershipProvider and RoleProvider implementations are used (inside the AccountController which delegates calls to those implementations).
I would like to use NHibernate in order to be able to read/edit/modify the values on that tables which are managed by ASP.NET Membership.
I found two solutions:
Write a custom NHibernate implementation for MembershipProvider and RoleProvider (or even use this one). That's the hardest path.
Map only the tables (as described here) and then use NHibernate directly (although any default actions from AccountController will still handled by the default providers).
Any suggestions/recommendations?
I've used the custom provider you link with pretty good success. I did make a few changes to it, so that it would use a single session for its lifetime.
If you want to use ASP.net membership I think that approach is your best bet, mainly for portability (it doesn't rely on any SP's being present in your database). I'm currently using the modified provider from that link against MSSQL and Postgres with no problems, and I've used it against MySQL as well.
I currently have an ASP .NET MVC / EF4 project that contains many pieces of autonomous functionality such as a blogging, events, contests, wiki, etc.
The entities used by each system are all mapped to my database through one giant EDM file.
This works well for the main site, but I also have a few personal sites where I want to reuse just the blogging functionality from the mains ite.
My biggest problem is that due to the mac daddy EDM file, my blog sites have to constantly have their database schemas updated to reflect changes made to areas of functionality that they don't use (i.e. changes to the events system).
The only other gotcha is that there are some entities (Users and Tags) that have relationships with entities from each area of functionality, making it hard to simply split each area of functionality off into its own EDM.
With all of this said, I'm trying to figure out the most efficient way to set this up.
Should I go down the road of splitting up the EDMs by each area (blogs, events, contests, wiki) and figuring out a way to maintain relationships for the User and Tag entities?
Or should I just perhaps be creating an EDM for each website that only maps the entities that it will actually need? The only problem with this is that my repository layer takes in a UnitOfWork/ObjectContext, and by creating new ObjectContexts for each site I'd have problems reusing my repository code.
You could setup a WCF service and then pass your data via a JSON contract. That way you'd have a central service that holds your EF data, and then just exposes functions based on what the your different applications need.
Its more short term work to setup (hopefully your service/repository layer was done with IoC in mind to allow it to be easily plugged in) but if your EF data changes a lot, it means you can update the one central service without having to update each of your clients apps.
There's a good reference thread here on S.O: https://stackoverflow.com/questions/973017/where-to-find-good-wcf-video-tutorials
With this question I am mostly looking for answers from people that have implemented the out-of-the-box ASP.NET membership in their own database - I've set up the tables inside my database and as far as I can see they contain mostly what I need but not everything. I will have the notion of a Firm (Company) to which Users will belong so I will have to associate the aspnet_Users with my Firms table (each user will be a member of exactly one firm).
If possible, provide some guidelines how did you do it and what I might run into if I have to modify the table design at some point in the future. Preferably I will be using the default Membership provider.
I am having trouble to decide whether to go from scratch or use what ASP.NET already offers.
I would suggest that you need to use a table-based Profile Provider implementation such as this one that Scott Guthrie blogged about. It is much better than the out-of-the-box profile provider as it allows you to define your own tables for profile information. In your case you would have a table that contains a Row per user and a FirmId and anything else you like such as nick name, social security number, whatever.
It works with the default Membership provider so you won't have to make any changes to it. There are two implementations in the example, a Stored Procedure based one and a Table based one. I prefer the second but they are both very easy to use.
The default profile provider proved a bit rubbish because it stored all of a user's information in a single field. The provider that I suggested solves this in a very efficient way.
I decided not to use ASP.NET Membership provider and its default tables because of the changes that might be introduced in future versions, so I eventually ended up using this custom Entity Framework provider by OmidID although I had to tweak it quite a lot. But I can now say that we have a rather fullproof entity framework based membership provider that we can easily maintain and indenpendent of the ASP.NET membership tables in SQL Server.
I would treat the ASP.NET membership as a separate service. Just use it as is and add any additional functionality on top of it.
In this case just create a table which links the users to the companies but don't alter the ASP.NET tables. If you have any additional information you need to store about users put this in another table which is associated with the ASP.NET membership users table.
Update: I've started using this ASP.NET MVC Area to administer users and roles https://github.com/TroyGoode/MembershipStarterKit. It comes with all the necessary models, views and controllers and is fully unit tested. Didn't take more than an hour to get it integrated into my site and up and running.
I'm creating (really, re-creating) an app that has existing user and other data in MS-Access databases. The data will be moved to SQL Server, and part of that involves migrating users. I want to use EF to do ORM, and I am pretty sure I know what the data model will be in SQL Server. I am new to EF but not to ASP.NET, and I'd like to take advantage of the Membership features in ASP.NET. I am thinking about several ways to do this and would like some advice. I've done only a little research about this idea thus far, maybe it's been answered elsewhere. So, here goes a cluster of related questions.
Can EF work with directly with ASP.NET Membership through some class or namespace that I'm not aware of?
If I transition users to the Membership system, to align their userids with data in other tables should I create another set of tables for user data atop the aspnet_* tables a la DotNetNuke?
I want to avoid a situation where I use the built-in Membership functions for only user authentication and switch over to EF context when I'm working with user-tagged data. Seems clumsy to withdraw user info to bind to a column in a GridView by going into a Membership user for every row, but maybe that's what's needed? Do I need to suck it up and replicate the Membership classes in EF for data retrieval purposes?
I was thinking of maybe implementing some kind of EF provider for Membership, on the idea that maybe then the provider could sit inside the overall EF data model. Is this crazy talk? (I've never written my own provider before)
Feel free to tell me I am not making any sense.
Why not do it the other way around? You can implement your own Membership provider for asp.net, that uses the model you want/need.
If the features you need aren't a complete match with the built-in asp.net membership implementation, you can just roll your own provider. If you will use just a couple features, you will have to implement just a couple methods (you don't have to fill implementation for all the methods). If you need more features than it supports, using the membership provider might get in your way.
We do, but we don't map the Membership tables. You shouldn't presume use of the SQL membership provider.
We map the user identity, not the DB id. Subtle, but important. Again, remember that there are other membership providers (e.g., domain auth).
Can you clarify the question? You won't need to replicate all of membership info in your EF model, but you will need a list of known identities.
No, not at all crazy, but difficult and probably unnecessary.