I went through a custom profile provider example a while ago and I am
now revisiting it.
My database has all the dbo.aspnet_* tables created when I ran the aspnet registration
wizard. In these tables I have aspnet_Profile which has a FK constraint pointing to aspnet_Users.
I also have two tables in MyDB: The first, dbo.ProfileData, has a foreign key constraint
pointing to dbo.Profile.
What I want to understand is how the tables in MyDB relate to
those in dbo.aspnet_*. Shouldn't there be a foreign key constraint (or some kind of
relationship) between the profile tables in MyDB and the aspnet tables? Some discussion
of how my custom tables relate to those provided by aspnet would be wonderful.
Thanks in advance.
There are two options I can see, both of which will yield basically the same result:
FK from dbo.aspnet_User.UserID to dbo.Profile.UserID, then define a unique key on dbo.Profile.UserID (unless you use it as the PK column for dbo.Profile)
FK from dbo.aspnet_Profile.ProfileID to dbo.Profile.ProfileID
dbo.aspnet_User is logically 1 - 1 with dbo.aspnet_Profile, so it doesn't really matter which approach you use as you will still get the same relational integrity.
If you are replacing the standard profile data table with your own implementation then it makes more sense to use the first suggestion, otherwise if you are extending the Profile schema then use the second suggestion.
EDIT
aspnet_Profile is the standard table - the standard SqlProfileProvider stores the user's profile data as a serialized property bag in aspnet_Profile, hence why there is no separate aspnet_ProfileData table as well.
This approach allows the profile schema to be customized easily for different applications without requiring any changes to the underlying database, and is the most optimal solution for a framework such as .NET. The drawback is that SQL Server does not have easy access to this data at all, so it is much more difficult to index, update and query the user's profile data using T-SQL and set-based logic.
The most common approach I have seen to remove this limitation is to extend the standard SqlProfileProvider to write to a custom profile data table which has specific columns for application-specific profile properties. This table naturally has a 1-1 relationship with the aspnet_Profile table, so it has a foreign key as indicated above.
The role of the extended provider is to promote specific profile properties to columns during profile writes, and read in the columns when the profile is retrieved.
This allows you to mix-and-match storage solutions on an as-needs basis, as long as your extended provider knows how to fall back to the standard implementation where it does not 'know' about a given property.
I always think it is best to leave the standard membership tables as-is, and extend where necessary using new tables with appropriate foreign keys, then subclass the appropriate provider and override the provider methods with your own implementation (calling into the base implementation wherever possible).
Related
I'm a MSSQL developer who recently was tasked with building a new application using DynamoDB since we use AWS and we wanted a highly scaleable database service.
My biggest concern is data integrity. For example, I have a table for all my users where every row needs to have a username, email, and name field, all strings, with a verified field that's an int. Is there anyway to require all entries in that table to have those fields and to be of that particular type?
Since the application is in PHP I'm using Kettle as my ORM which should prevent me from messing up the data integrity but another developer voiced a concern about if we ever add another application or if someone manually changes some types via the console.
https://github.com/inouet/kettle
Currently, no, you are responsible for maintaining the integrity of your items with respect to the existence of attributes that are not keys on the base table. However, you can use LSI and GSI to enforce data types of attributes (notwithstanding my qualm that this is not a recommended pattern, as it could cause partition heat especially for attributes whose range of values is small). For example, verified seems like it might take only 0 or 1 as a value, so if you create a GSI with PK=verified where verified is a Number, writes to the base table may get throttled by the verified GSI.
I have a couple of questions regarding Membership Provider. My textbook got me started but I still need more information.
I am using Linq to Entities, does it make sense to also create LINQ entity relationships with my membership provider DB?
I would like to add additional user attributes other than provided in the membership provider. Can I add them to the aspnet.USER table without any issues?
My users will join the website and will gain privildges as they participate, much like Stack Overflow. I want to keep track of their postings by adding a field to the user table to manage that function.
Thanks in advance!
There are two ways to associate additional information with user accounts when using the Membership model. The first - which affords the greatest flexibility, but requires the most upfront effort - is to create a custom data store for this information. If you are using the SqlMembershipProvider, this would mean creating an additional database table that had as a primary key the UserId value from the aspnet_Users table and columns for each of the additional user properties. In the online messageboard example, the table might be called forums_UserProfile and have columns like UserId (a primary key and a foreign key back to aspnet_Users.UserId), HomepageUrl, Signature, and IMAddress.
Rather than using custom data stores, the ASP.NET Profile system can
be used to store user-specific information. The Profile system allows
the page developer to define the properties she wants to associate
with each user. Once defined, the developer can programmatically read
from and assign values to these properties. The Profile system
accesses or writes the property values to a backing store as needed.
Like Membership and Roles, the Profile system is based on the provider
model, and the particular Profile provider is responsible for
serializing and deserializing the property values to some data store.
The .NET Framework ships with a SqlProfileProvider class by default,
which uses a SQL Server database table (aspnet_Profile) as its backing
store.
Examining ASP.NET's Membership, Roles, and Profile - Part 6
By Scott Mitchell
This should get you started. I guess I could answer your questions as follow:
It shouldn't be necessary. Explore the membership API, everything you ever wanted is... probably in there.
Read the article and decide what's best.
Good luck, :).
Sincerely,
Maxime
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.
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.
I'm working on an ASP.NET4.0/C# application for a public site that needs to authenticate only the employees that work at the associated business. The idea is for the site to have a CMS such that employees can go in and make changes to certain content without having to work with any html.
My question relates to the design and use of a ASP.NET membership provider. I'm not trying to make the site work with an existing database, so there's no need to create my own MembershipProvider for that purpose. However, since each user is an employee, I want to track additional information such as name and office number. I can think of two readily apparent ways to accomplish this:
Use the default SqlMembershipProvider class. As a result, I would need to add the appropriate tables to my database and create a separate table for any "additional" information I want to store. This effectively creates a vertical partition on the user table, since I would use the asp.net-assigned userID as the primary key of the employee table as well. To retrieve the "additional" information, I could ask the provider for information about the current user and requery the database in the event I want to know anything else.
Create one table for all employee information (including login and password) and create my own custom MembershipProvider and MembershipUser classes with the functionality I desire.
I've also considered the use of profiles to store such information, however, the site will publicly contain employee listings, and these pages will need to access some of this information. As a result, I should probably cache this data and it seems like using the serialized fields that profiles provide would cause a problem.
Thus, purely in regards to design... would it be best to make a distinction between a user and an employee and use the default SqlMembershipProvider and associated tables, or write my own user tables that store the information I need and my own MembershipProvider for accessing that information?
If I understand your question correctly, you'd like to store additional user info within the ASP.NET Membership. I've created a number of sites using the following setup.
Install the default .NET Membership using the aspnet_regsql.exe tool
Create a UserProfile table with a uniqueidentifier (PK) UserID column that is linked via a foreign key to the aspnet_Users table
To access that information, all you need is the UserId of a particular User, then you can query your custom table for more information.
Microsoft has written an excellent post on how to do this.
Good luck!
M
I am doing something similar, using your option 1. Works great for me.
My business logic has some functions for mutating users. It knows when to touch my users table or the Membership functionality.
Using a custom MembershipProvider for this sort of thing will give you more work than you bargained for.
SQL Table profile provider (http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx ) will help you do just that.
You will get the power of the Profiles and on the same time not worry about caching or serialization since this provider stores the profile information in clear database table without any serialization. You can use them directly in your queries.