I need people's advice as to whether this the best way to achieve what I want. Apologies in advance if this is a little to subjective.
I want to use Entity Framework V.1 to create something similar to the following C# classes:
abstract class User
{
public int UserId;
public string TelephoneNumber;
}
class Teacher : User
{
public string FavorateNewspaper;
}
class Pupil : User
{
public string FavorateCartoon;
}
I need people's advice as to how to best to persist this information.
I plan to use SQL Server and the normal Membership Provider. It will create for me a table called aspnet_Users. There will be two roles: Teacher and Pupil.
I will add fields to the table aspnet_Users which are common to both roles. Then create tbl_Teachers and tbl_Pupils to hold information specific to one role.
So My database will look a bit like this:
aspnet_Users
int UserId
varchar TelephoneNumber
tbl_Teachers
int UserId
varchar FavorateNewspaper
tbl_Pupils
int UserId
varchar FavorateCartoon
The idea of course being that I can match up the data in aspnet_Users to that in either tbl_Teachers or tbl_Pupils by joining on UserId.
So to summarise, my questions are:
Is my database structure the best option to achieve these classes?
Should I try to wrap the Entities within my own POCO classes?
Should I change my database structure so that EF creates entities which are closer to the classes I want?
EDIT: I re-arranged my question it make it a bit clearer what I'm asking.
If you're using EF 1, then POCO can be a bit unpleasant. Unless there's a good reason not to, I'd just use normal EF entities. Your database model is fine, by the way, and is an example of TPT (Table Per Type) inheritance mapping. You could either use the wizard to create entites from the databaes, or create your entites and map them to the associated tables. If you do the former you'd initially end up with three unrelated entities. You'd then use the designer to tell EF that Pupil and Teacher inherit from User, and that User is abstract.
In general, one of the strengths of EF is that the entities don't have to match that closely to the tables that persist them. In this case though there's a natural mapping.
Related
I have the following class model:
I must make sure that an employee only has one role belonging to a project. So if Project A has the roles roleA and roleB, then the employee is only allowed to have one of them(but hes obviously allowed to have a role from another Project, but again, only one).
I make sure that thats always the case in my business logic. So before i add a role to an employee, i check whether the employee already has a role which belongs to the project of the role he wants to add, etc. So using my API/business logic, im able to make sure that the must criteria is fullfilled.
But should i add an extra layer of security on the database level? I could add triggers which check the above mentioned criteria. That would make it absolutely impossible to add any data into the database which violates my criteria. Is that extra layer of security on database level needed or is it enough if i do the validation in my business logic? And is a trigger the correct best way to do it?
Edit:
I implement what the comments suggested the following way:
My IdClass implementation:
#Data
public class TestId implements Serializable {
private Project project;
private Employee employee;
}
The class implementing the ternary association, making the employee and project pair unique:
#Entity
#Data
#IdClass(TestId.class)
public class Test {
#Id
#ManyToOne
private Project project;
#Id
#ManyToOne
private Employee employee;
#ManyToOne
private ProjectEmployeeRole projectEmployeeRole;
}
There are two questions in one.
Database: If you want the database to enforce this rule, you do not need any trigger. Just implement the many-to-many relation between Employee and Project using an association table with a primary key made of EmployeeId and the ProjectId: the combination must be unique. In the association table you'd also store the sole role this employee would have on that particular project.
UML class diagram: your diagram is misleading, since there are a lot of many-to-many association, but unfortunately, you say that one particular role can appear only in one project. A clearer way to represent this in UML would be to represent a ternary association (the association table I mentioned for the database would in fact impelment this ternary association). Another variant would be to use an UML association class and this association class could itself have an association with the role.
I read through Apress - Pro Asp.Net MVC 5 and the free chapters of the Identity Framework and now, I want to create a small sample application with some data and Identity.
Later I want to make a test deployment to Windows Azure.
Now, should I create one single Database for this Application, containing all Data (Products, whatsoever, IdentityData (User-Accounts, Oauth Linkings...)) or would it be better to create two Databases?
I know, If I'd create two, I would be able to use the same Identity-Data for other MVC Applications, but is there some kind of best practice for MVC?
There's no "best practice", per se, in this area. It depends on the needs of your individual application. What I can tell you is that if you choose to use multiple database, you'll end up with a somewhat fractured application. That sounds like a bad thing, but remember this is a valid choice in some scenarios. What I mean by that is simply that if you were to separate Identity from the rest of your application, requiring two databases and two contexts, there's no way, then, to relate your ApplicationUser with any other object in your application.
For example, let's say you creating a reviews site. Review would be a class in your application context, and ApplicationUser would of course be a class in your Identity context. You could never do something like:
public class Review
{
...
public virtual ApplicationUser ReviewedBy { get; set; }
}
That would typically result in a foreign key being created on the reviews table, pointing to a row in your users table. However, since these two tables are in separate databases, that's not possible. In fact, if you were to do something like this, Entity Framework would realize this problem, and actually attach ApplicationUser to your application context and attempt to generate a table for it in your application's database.
What you could do, though, is simply store the id of the user:
public string ReviewedById { get; set; }
But, again, this wouldn't be a foreign key. If you needed the user instance, you'd have to perform a two step process:
var review = appContext.Reviews.Find(reviewId);
var user = indentityContext.Users.Find(review.ReviewedById);
Generally speaking, it's better to keep all your application data together, including things like Identity. However, if you can't, or have a business case that precludes that, you can still do pretty much anything you need to do, it just becomes a bit more arduous and results in more queries.
From my understanding, cakephp doesn't support database inheritance relationship. However, I want to create a database with different type of Users.
In this case, there are three types of Users: Seller, Customer, and Administrator. Every users should have basic User information such as password, username, etc.
However, each types of users will have its own unique set of datas. For example, seller may have inventory_id while customer may have something like delivery_address, etc.
I have been thinking of creating a workaround to this problem without destroying cakephp convention. I was going to create three additional foreign keys, admin_id, seller_id and customer_id, inside User table, which links to other table. However, knowing that this is an IS-A relationship not HAS-A, I would have to make sure that two of the ids are NULL value. Therefore, this workaround seems ugly to me..
Is there any other simpler, better approach?
For this type of database structure I would probably look at adopting an Entity-Attribute-Value model. This would mean your customer may have a delivery_address and your user may have an inventory_id but as far as your relationship in Cake is concerned your both your user and customer would just have an attribute_id ... you can then create another table that stores what type of attributes are available.
It it's simplest form, your user and customer would be attached to an *attribute_lookup* or *attribute_link* table by a hasMany (probably) relationship. That attribute_lookup/link table would be connected by a belongsTo/hasOne relationship to the actual Attribute Type and Attribute Value models.
Providing that you normalise your tables correctly, you can stick well within Cake relationship conventions.
You can read more about EAV here.
I have been thinking about this problem for some time now, and I have eventually got around to build a solution for it. What I came up with is a new ORM that can be used on top of CakePHP.
It sort of works as CakePHP 3.0 with entities that represent an id/model, but it is much more advanced and supports multi table inheritance and single table inheritance.
Check it out: https://github.com/erobwen/Cream
What rules should i follow in order map efficiently entities from my domain model to a database table?
Should database columns be aligned with domain class properties?
For example i have a Database table
Person {(varchar)FirstName, (varchar)LastName, int(age)}
And a Domain class
class Person(){
String firstName;
String lastName;
int age;
}
Should the class and the table
contain the same number of properties
Should they be of the same corresponding
type (e.g : varchar - string)
What are the best practices
What to avoid?
There are many strategies for object-relational mapping. Ultimately you have to represent every piece of persistent data in a field somewhere, so your strategy will work. Other questions you'll have to answer:
1) How are your records keyed? Are you going to have a unique ID field for each class?
2) How will you handle inheritance? If you have a PersonA(Person) class that introduces an additional field, will you create a whole new table for every field in Person + PersonA, or just have a PersonA table for the additional field?
3) How are you planning to construct queries against the database? Are you going to provide some form of object-query mapping?
There are many open source ORMs out there, so unless you're doing this for a research project, I'd advise that you use one of them.
Is this how one would normally design classes?
One class = 1 Table.
How about tables that contain a foreign key to another table?
Suppose I have the following:
PersonTable
---------------
person_id
name
PersonMapTable
---------------
map_id
type_id (fk)
person_id
PersonTypeTable
-------------------
type_id
description
parent_type_id
AddressTable
-------------------
address_id
address1
address2
city
state
zip
AddressMapTable
-----------
address_map_id
address_id
person_id
Would good practice consist of creating a class for each table?
If so, what are the best practices for loading/saving such classes back to the database without an orm? A simple code example would be really helpful
I'd recommend reading Martin Fowler's Patterns of Enterprise Application Architecture, which has several patterns of mapping between classes and tables.
I don't think that one object per table is necessarily a good design. It's hard to give a one size fits all rule, but objects can be richer and more fine grained. A database can be denormalized for reasons that don't apply to objects. In that case, you'd have more objects than tables.
Your case would include 1:1 and 1:m relationships:
public class Person
{
// 1:m
private List<your.namespace.Map> maps;
}
public class Map
{
// 1:1
private your.namespace.Type;
}
For the most part I tend to map tables to entities, but it's not a hard rule. Sometimes there are instances where the repository for a specific entity in question is better off dealing with the general concerns surrounding a specific entity, which means it will cross into dealing with other tables as a result, without those tables specifically needing to exist as entities.
What I never do (except in very specific planned cases where the dependent data ALWAYS needs to be retrieved with the entity), is set an entity or collection of entities as a property of another entity. Instead, that entity will either be discoverable via its ID, which will either be a property of the parent entity or discoverable via the associated repository in relation to the parent entity.
In cases where I need the child entity or entities of another entity to be bundled together, I'll make use of an "info" helper class to pull together all the required data. For example, if I have an entity class Widget and it has a collection of child Part objects, then I would create a WidgetInfo class which would contain the Widget instance as a property and a collection of Part objects as the other property.
This way all entity classes remain as lightweight as they can and never make the assumption that dependent data will need to be loaded. Also it keeps the repository model clean without forcing you into messy ORM territory which is generally the case if you create child object collections on an entity class. If you do that without ORM, then you end up with the messy problem of when to load the children or not, and when to assume that the children have or have not been loaded.
I wouldn't say that I always have class per table, especially when you have many to many relationships. Based on your table above I would have 2 classes... I am not sure why you have both and id and a person_type_id, to me they would be the same thing but here are the classes.
Person
{
public int Id { get; set; }
public string Name { get; set; }
public List<PersonType> { get; set; }
}
PersonType
{
// I would discourage from using Type as property name as it is a keyword...
public string [Type] { get; set; }
}
Unless your users are data entry clerks, it's generally considered better to design classes from Use Cases/User Stories. Even if the database already exists.
Reason? It's too easy for users to end up assuming their job is to exercise the software, rather than expecting the software to help them do their jobs.
Clearly they need to intersect at some point. I concur that Fowler's book is a great place to start. But I think he'll reinforce this point of view.
If you want a modeling perspective that helps you get both the classes and the database right, consider Object Role Modeling.
If you plan on using Object-Relational Mapping (ORM), this may affect your table design. Hibernate, for instance, does not like mixed inheritance mapping strategies within the same tree.
Since you specifically indicated that you will not be using ORM, you can follow traditional database design principals. This typically means starting with one table per class, normalizing to third-normal form (read about database normalization here), then denormalizing to meet performance constraints (read about denormalization here).
Regarding your question about how to load and save the objects without the use of ORM, a common strategy is to use Data Access Objects (DAOs). Here is a simple example:
public interface ICustomerDao
{
public void insert(Customer customer) throws CustomerDaoException;
public void update(long id, Customer customer) throws CustomerDaoException;
public void delete(long id) throws CustomerDaoException;
public Customer[] findAll() throws CustomerDaoException;
public Customer findByPrimaryKey(long id) throws CustomerDaoException;
public Customer[] findByCompany(int companyId) throws CustomerDaoException;
}
You didn't specify which language you are using, but regardless you may find this example using Java generics for DAO useful.
Would good practice consist of
creating a class for each table? If
so, what are the best practices for
loading/saving such classes back to
the database without an orm?
You are using ORM. You are mapping objects to relational tables. Whether you use a pre-built library to do so or not is your call. If you don't, you'll be essentially implementing one yourself, though probably without all the bells and whistles of existing ORMs.
The two most common ways of doing this are the ActiveRecord pattern and the Data Mapper pattern. Each has its advantages and disadvantages.
With the ActiveRecord pattern, you define classes whose attributes define the table columns for you. Each instance of this class corresponds to a row in the database, and by creating (and saving) a new instance, you create a new row in the database. More information on that is available here: http://en.wikipedia.org/wiki/Active_record_pattern
In the Data Mapper pattern, you define table objects for each table, and write mapper functions which assign columns of the table to existing classes. SQLAlchemy uses this pattern by default (though there are ActiveRecord type extension modules, which adapt SQLAlchemy's functionality to a different interface. A brief introduction to this pattern can be found in SQLAlchemy's documentation here: http://www.sqlalchemy.org/docs/05/ormtutorial.html (read from the beginning up to but not including the section entitled, "Creating Table, Class and Mapper All at Once Declaratively;" that section explains ActiveRecord using SQLAlchemy).
The ActiveRecord pattern is easier to set up and get working with, and gives you classes which are clearly representative of your database, which has benefits in terms of readability. As a side benefit, the declarative nature of ActiveRecord classes effectively acts as clear and straightforward documentation for your database schema.
The Data Mapper pattern gives you far more flexibility in how your data maps to your classes, so you aren't tied to a more-or-less one-to-one relationship between tables and classes. It also separates your persistence layer from your business code, which means that you can swap out other persistence mechanisms later, if need be. It also means you can more easily test your classes without needing to have a database set up to back them.
For more in depth discussion of SQLAlchemy's mapper configuration, check out http://www.sqlalchemy.org/docs/05/mappers.html. Even if you aren't planning on using a library like SQLAlchemy, the documentation should help you see some of the options you may want to consider in mapping your classes to database tables.
This DataBase to Class point of view approach is more than likely to lead you to cranking lots of code quite quickly. However, a good chunk of this code will likely not be of any use or require some severe mutation. In other words, you'll likely build specific classes that mismatch your displays and workflow.
First, consider your apps, your users' needs, general workflow .. etc Actually come up with something that looks workable (i.e. mock your displays).
Concentrate on the classes you need to use the displays and model your storage (db design) after those needs. Chances are that you will have only a few of straight-table classes as most of your classes will naturally tend provide the solution for your displays.
Good luck.