What are the reasons behind the schema of the ASP.NET Membership DB schema? - asp.net

The following questions are about the DB set up with aspnet_regsql.exe (for .NET 4):
Why is the username stored in aspnet_Users both in original form and in lowercase? Why not lowercase all the time?
Why are Users and UsersMembership two distinct tables? Is this just because we can have different membership/application or is some best practice?
Should data like "IsApproved" be stored in DB like a column? For me it seems like a temporary column that, once approved, could be removed. So why not store it a table with key/value pairs (something like "ExtendedpProperties). Similar for other columns like "Comment" or "LastLockoutDate".
What is the purpose of "LastUpdatedDate" in "aspnet_PersonalizationPerUser"?
Why are there two columns for Value in aspnet_Profile?
Is there something wrong in that DB? Do you think that it should have been designed in another way? Please provide arguments.
Thanks!

The idea of any calculated column is to save cycles on doing those calculations during querying. Most especially during large queries. The other thought is one which you had in indexing those columns. Again, this is done to save cycles.
The membership table holds information related to the MembershipProvider API interface. The users table stores usernames and user ids, which are referenced from many providers.
The aspnetdb system is very modular and each piece can be customized through the various providers. The tables need to be separated so each interface can be rewritten, redirected, etc.
Where do you want to store this information else?
Maybe you want to know when the user or the application last changed WebParts
PropertyNames holds a string value containing information about the profile property values present in the PropertyValuesString and PropertyValuesBinary fields. The string holds a colon-delimited list of items.

Looks like, you have been given an assignment , everything is there for a reason go through Asp.net Membership Documentation

Related

Avoiding third table in many to many relationship

I want to create a sqlite database with at least two tables: account and service. One account can have several services and one service can be used by several accounts.
I would like to be able to query all the services which one account uses.
Now, where it gets complicated for me is that I would like to avoid a third table which is usually used - as far as I know - to resolve this many-to-many relationship.
Is there an appropriate way to do this?
Thank you!
You can denormalize your schema and store relations in a field containing an array in each table. But this is going to be less efficient to query and not all database engines support array type. Actually sqlite3 doesn't. You can mitigate that by storing that as a JSON data type which will be then an array in JSON representation.

How to combine using Membership API with own application related data?

Designing a new application in asp.net 4 I have to make a decision how to use a MS SQL Membership API along with my own data in the MS SQL data base. Firstly I need to store and access user profile data in more flexible manner then the Profile provider supports. Secondly I would like to link other user related information (e.g. Orders).
No matter where you store your aspnetdb tables (in the separate data base or in the same data base with your data), the problem stays how to keep your data synchronized.
After a research I see the following relevant options:
1. Foreign key UserId from asp_Users (suggested in this tutorial).
2. No foreign key - use transactions (suggested here).
3. No foreign key - use customized AccountController (whatever it is, suggested here).
4. Additional table which links Membership UserId (uid) with custom UserId (int).
5. ...
On the one hand I like the first solution as it is quite straightforward and is suggested in an official asp.net tutorial.
On the other hand opponents note quite reasonably that using foreign keys breaks the general idea of providers which are supposed to help separating concerns and to be interchangeable. But unfortunately they do not go much into implementation details so it is not really easy to estimate those suggestions in terms of relevance and ease of implementation.
So what is the best option to approach this? Furthermore how would the implementation look like? Would it be enough to use just additional ADO.NET or LINQ etc code or is it worth implementing a custom Membership and/or Profile Provider?
Thank you in advance.
The first is the simpliest approach. Add the GUID of the user as a foreignkey in the related tables (f.e. Ordered_by). I don't see where it breaks separating concerns. If you want to keep the order-record in database, you also have to keep the user who has ordered, that makes perfectly sense.
I have used option 4 successfully in my current application. I've created a table aspnet_UserID with idUser int as primary-key and fiUser(the GUID of the aspnet_Users) as foreign-key. Here is the model:
(Note: User is the standard aspnet_Users table created via aspnet_regsql.exe and aspnet_UserId is my custom table that maps every Guid with my int-ID)
Now i'm storing only my idUser as FK in all related tables (like in your Order-Table). That has the advantage of less storage and more readable UserID's(i could never remember a GUID). Maybe it's somewhat more separated with this "wrapper-table" but that was not my main intention.
You can change the delete-rule on your foreignkeys if you want to control the behavior. Set it to Cascade if you f.e. want to delete all orders that were ordered by the user you're deleting or set it to no Action if you want to keep this order.
I can't suggest any alternatives for the Profile question because you haven't mentioned what you mean with "need to store and access user profile data in more flexible manner then the Profile provider supports".
You should consider writing your own custom membership provider that uses the tables/data as per your need (instead of using ASP.NET provided schema).
See this MSDn sample (schema, code) for writing a custom provider - this sample uses OLEDB to access database. Yet another sample is here - it uses active directory as a store.

ASP.NET Dynamic Data: Access rights only to specific rows

I want to use ASP.NET Dynamic Data for my next project, but there is a problem a can't manage to solve. In the database we manage authorization on a per-row basis. For example no user is permitted to see all rows of the Contracts table. So there is a Many to Many Relationship between Contracts and Users. So everytime Dynamic Data performs a Select to show all Contracts it has to look into the ContractUsers junction table to see what contracts the current user is permitted to see (filtered by UserID which will be stored in a session variable). Of course these junction tables should be invisible to the users.
By default Dynamic Data returns all rows of a table, so is it possible to customize this behaviour for every query the user performs?
I want to use Dynamic Data together with LINQ to SQL but if this task would much easier to accomplish using Entity Framework I would look into that too.
Thanks for your help and time.
Implementing such a solution in Dynamic Data it will probably require the creation of a custom Entity Template; not really easy but once done it will not require the creation of custom pages just the editing of the page templates.
I think it will be really usefull to check the excellent work on DD done by S.J.Naughton and presented on his blog.
Greetings, F.
You should not use dynamic data because you need full control over querying and manually write all linq queries to add your data level security. If you still insist on dynamic data be aware that you will still write most of pages yourselves and you will only use dynamic templates. You will have to manually define ever data source and correctly pass where condition to filter results based on logged user.
In addition linq-to-sql is not able to hide junction table and entity framework is able to do that only if junction table contains just two FKs for many-to-many relation. If this table contains any other column you want to use in the application you will have to map it as any other entity and dynamic data will show it as an entity.
Dynamic data are technology for quick creation of simple application where you need to provide access to database through web interface but what you describe is not a simple scenario. You need per record authorization which can differ among entity types.

sql server database design

I am planning to create a website using ASP.NET and SQL Server. However, my plan for the database design leaves me wondering if there is a better way.
The website will serve as a repository of information for various users. I figure I would have two databases, a Membership and Profile database.
The profile database would contain user data for all users, where each user may have ~20 tables. I would create the tables when the user account is created and generate a key used to name the tables. The tables are not directly related.
For Example a set of tables for two different users could look like:
User1 Tables - TransactionTable_Key1, AssetTable_Key1, ResearchTable_Key1 ....;
User2 Tables - TransactionTable_Key2, AssetTable_Key2, ResearchTable_Key2 ....;
The Key1, Key2 etc.. values would be retrieved based on the MembershipID data when the account was created. This could result in a very large number of tables over time. I'm not sure if this will limit scalability by setting up the database in this way. Any recommendations?
Edit: I should mention that some of these tables would contain 20k+ rows.
Realistically it sounds like you only really need one database for this.
From the way you worded your question, it sounds like you're trying to dynamically create tables for users as they create accounts. I wouldn't recommend this method.
What you want to do is create a master table that contains a primary key for each individual user. I'm assuming this is the Membership table. Then create the ~20 tables that you need for the profiles of these members. Every record, no matter the number of users that you have, will go into these tables. These 20 tables would need to have a foreign key pointing to the unique identifier of the Membership table.
When you want to query a Member for their user information, just select from the tables where the membership table's primary Id matches the foreign key in the profile tables.
This would result in only a few tables in the end and is easily maintainable and follows better database design.
Your ORM layer (EF, LINQ, DAL code) will hate having to deal with one set of tables per tenant. It is much better to have either one set of tables for all tenant in a single database, or a separate database per tenant. The later is only better if schema upgrade has to be vetted by tenant (like Salesforce.com has). If you can afford to upgrade all tenant to a new schema at once then there is no reason for database per tenant.
When you design a schema that hold multiple tenant the important things to remember are
don't use heaps, all tables must be clustered index
add the tenant ID as the leftmost key to every clustered
add the tenant ID as the leftmost key to every non-clustered index too
add the Left.tenantID = right.tenantID predicate to every join
add the table.TenantID = #currentTenantID to every query
These are fairly simple rules and if you obey them (with no exceptions) you will get a perfect partitioning per tenant of every query (no query will ever ever scan rows in a range of a different tenant) so you eliminate contention between tenants. To be more through, you can disable lock escalation to make sure no tenant escalates to block every other tenant.
This design also lends itself to table partitioning and to sharing the database for scale-out.
You definitely don't want to create a set of tables for each user, and you would want these only in one database. Even with SQL Server 2008's large capacity for tables (note really total objects in database), it would quickly become unmanageable. Your best bet is to use 20 tables, and separate them via a column into user areas. You might consider partitioning the tables by this user value, but that should be tested for performance reasons too.
Yes, since the tables only contain id, key, and value, why not make one single table?
Have the columns:
id, user ID, key, value
Put an Index on the user ID field.
A key idea behind a relational database is that the table structure does not change. You create a solid set of tables, and these are the "bones" of your application.
Cheers,
Daniel
Neal,
The solution really depends on your requirement. If security and data access are concern and you have only a handful of users, you can set up a different db for each user with access for him set to only his/her database.
Other wise, what Daniel Williams suggested is a good alternative where you have one DB and tables laid out with a indexed column partitioning the users data rows.
It's hard to tell from the summary, but it looks like you are designing for dynamic attribution by user. This design approach is called EAV (Entity-Attribute-Value) and consists of a simple base collection key (UserID, SiteID, ProductID...) and then rows consisting of name/value pairs. In a more complex version, categories are sometimes added as "super columns" to the tuple/row and provide sub-groupings for a set of name/value pairs.
Designing in this way moves responsibility for data type integrity, relational integrity and tuple integrity to the application layer.
The risk with doing this in a relational system involves the breaking of the tuple or row into a set of rows. Updates, deletes, missing values and the definition of a tuple are no longer easily accessible through human interaction. As your application evolves and the definition of a tuple changes, it becomes almost impossible to tell if a name/value pair is missing because it's part of an earlier-version tuple or because it was unintentionally deleted. Ad-hoc research as well becomes harder to manage as business analysts must keep an understanding of the virtual structure either in their heads or in documentation provided.
If you are looking to implement an EAV model, I would suggest you look at a non-relational solution (nosql) like MongoDB or CouchDB. These stores allow a developer to save and retrieve "documents" or json-formatted messages that are essentially made up of a collection of name/value pairs and can look very much like a serialized object. The advantage here is that you can store dynamic attribution without breaking your tuple. You always know that you have a complete tuple because you can store and retrieve it as a single "blob" of information that can be serialized and deserialized at-will. You can also update single attributes within the tuple, if that's a concern.
MongoDB also provides some database-like features such as multiple-attribute indexes, a query engine that is robust in comparison to other similar non-relational offerings and a sharding solution that is much less trouble than trying to do it with MySQL.
I hope this helps.

is there a way to get all profiles in ASP.NET membership

Is there an API in the ASP.NET membership, implementation to get all user profiles at once. If not, is there another good way to get all the names (first + last) of all the users. I'm trying to avoid the many SQL requests generated by getting the user profiles one at a time.
ProfileProvider.GetAllProfiles().
I'd still recommend just adding first and last names to the MembershipUser though. You'll need to cast your provider to the concrete type, which is brittle if you ever want to change it.
Update:
A challenge with the way profile data is stored is that the property names and values are packed and stored in two columns in the Profile database. If you run the aspnet_Profile_GetProperties sproc you will see that.
There is no out-of-the-box sproc that gets profile data for all users. A quick modification to the aspnet_Profile_GetProperties would do that for you though.

Resources