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 (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 :
aspnet_regsql.exe
Web.Config
to use the SqlMembershiptProvider
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With