This question already has answers here:
What is an ORM, how does it work, and how should I use one? [closed]
(5 answers)
Closed 5 years ago.
As the title says; what is a ORM framework and what is it useful for?
A simple answer is that you wrap your tables or stored procedures in classes in your programming language, so that instead of writing SQL statements to interact with your database, you use methods and properties of objects.
In other words, instead of something like this:
String sql = "SELECT ... FROM persons WHERE id = 10"
DbCommand cmd = new DbCommand(connection, sql);
Result res = cmd.Execute();
String name = res[0]["FIRST_NAME"];
you do something like this:
Person p = repository.GetPerson(10);
String name = p.FirstName;
or similar code (lots of variations here.) Some frameworks also put a lot of the code in as static methods on the classes themselves, which means you could do something like this instead:
Person p = Person.Get(10);
Some also implement complex query systems, so you could do this:
Person p = Person.Get(Person.Properties.Id == 10);
The framework is what makes this code possible.
Now, benefits. First of all, you hide the SQL away from your logic code. This has the benefit of allowing you to more easily support more database engines. For instance, MS SQL Server and Oracle has different names on typical functions, and different ways to do calculations with dates, so a query to "get me all persons edited the last 24 hours" might entail different SQL syntax just for those two database engines. This difference can be put away from your logic code.
Additionally, you can focus on writing the logic, instead of getting all the SQL right. The code will typically be more readable as well, since it doesn't contain all the "plumbing" necessary to talk to the database.
From wikipedia:
Object-relational mapping (ORM, O/RM,
and O/R mapping) in computer software
is a programming technique for
converting data between incompatible
type systems in relational databases
and object-oriented programming
languages. This creates, in effect, a
"virtual object database" that can be
used from within the programming
language. There are both free and
commercial packages available that
perform object-relational mapping,
although some programmers opt to
create their own ORM tools.
It's good for abstracting the datastore (flat file / SQL / whatever) out in order to provide an interface that can be used in your code. For example, (in rails) instead of constructing SQL to find the first user in a users table, we could do this:
User.first
Which would return us an instance of our user model, with the attributes of the first user in the users table.
Databases usually work on relational model: you have tables (simplifying: like a spreadsheet), and relations between them - one-to-one, one-to-many, many-to-many, etc, meaning for instance that one record in table A has many related records in table B. You can retrieve data from them as rows (collection of values representing rows from table/tables) More in wikipedia.
Modern programming languages use object model. Objects have methods, attributes (simple or complex) etc.
ORM software does a transition between those models. For instance, it puts all related records from table B into an attribute of object A. This kind of software makes it easier to use relational databases (most popular kind) with object programming languages.
Whenever you go with ORM (Object Relational Mapper) you will find DBAL (Database Abstraction Layer) side by side. So its necessary to know what these are, so as to get good insights of what you are using and whats the advantages that you will get.
DBAL (Database Abstraction Layer)
It acts as a layer between your code and database. Irrespective of whatever your database, the code written will work fine with minor tweaking.
Assume that for the current project your using MySQL once its a fully matured and gets huge traffic your team plan to switch the database to Oracle for some reason then the code you have written in MySQL must be rewritten to Oracle based queries. And rewriting the queries for the whole project is a tedious task.
Instead if you use any DBAL libraries then you can switch the configuration of the database and make sure your project will be up and running within a day (May be with some minor tweaking).
ORM (Object Relational Mapper)
Object Relational Mapping (ORM) is a technique (Design Pattern) of accessing a relational database from an object-oriented language.
If you have used any kind of frameworks like Symfony (if you come from PHP background)/Hibernate (Java), then your familiar with these. Its nothing but Entities.
In order to access the database in Object Oriented context and interface translating the object logic is necessary, this interface is called as ORM. Its make up of the object that give access to data and keep the business rules with themselves.
Eg.
class User{
private $email;
private $password;
public function setEmail($email){
$this->email = $email;
return $this;
}
public function getEmail(){
return $this->email;
}
public function setPassword($password){
$this->password = $password;
return $this;
}
public function getPassword(){
return $this->password;
}
}
/* To save User details you would do something like this */
$userObj = new User();
$userObj->setEmail('sanitizedEmail');
$userObj->setPassword('sanitizedPassword');
$userObj->save();
/* To fetch user details you would do something like this */
$userObj = new User();
$userDetails = $userObj->find($id);
Eg. Doctrine, Propel, RedBean
ORM is:
An abstraction and like any abstraction it makes life easier for you.
From Wikipedia:
http://en.wikipedia.org/wiki/Object-relational_mapping
Object-relational mapping (ORM, O/RM, and O/R mapping) in computer software is a programming technique for converting data between incompatible type systems in relational databases and object-oriented programming languages. This creates, in effect, a "virtual object database" that can be used from within the programming language. There are both free and commercial packages available that perform object-relational mapping, although some programmers opt to create their own ORM tools.
Pros and cons
ORM often reduces the amount of code needed to be written, making the software more robust (the fewer the lines of code in a program, the fewer the errors contained within them).[1].
There are costs as well as benefits for using O/R mapping. For instance, some O/R mapping tools do not perform well during bulk deletions of data. Stored procedures may have better performance but are not portable.
It allows you to do things like this (this is Doctrine code):
$activeUsers = Doctrine::getTable('User')->createQuery('u')->addWhere('u.active = false');
foreach($activeUsers as $user)
{
$user->active = true;
$user->save();
}
Object-relational mapping (ORM) libraries provide this mapping of database tables to domain object classes.
Related
I wonder if you can help me, I was very excited around the release of Laravel 4.1 as I was sure that the new polymorphic relationships would solve a little development problem I had on the Horizon. Unfortunately, despite my best efforts I'm unable to bend any of the existing relationships to my will.
Essentially what I want is a one to many polymorphic relationship, so that I can "join" a query to any number of models, which can have different databases connections - I would like this to happen within Eloquent.
Unfortunately this relationship, to my surprise, doesn't seem to exist. All the polymorphic relationships I have seen require at least an entry on the polymorphic table for every entry on the connecting table - huge unnecessary data duplication for my purposes - and largely defeating the point of what I'm trying to do.
Below is what I have come up with as a work around but I dont want to start churning out custom code I have to maintain if I don't have to and I'm sure this must be possible. Does anyone know how to do this without resorting to the code below, also interested in tips to improve code for possible pull request if non-existent:
public function morphOneToMany($foreignKey, $localKey, $name = null, $type = null, $id = null)
{
if (is_null($name))
{
list(, $caller) = debug_backtrace(false);
$name = snake_case($caller['function']);
}
list($type, $id) = $this->getMorphs($name, $type, $id);
$class = $this->$type;
return $this->hasMany($class, $foreignKey, $localKey);
}
More details on laravel forums: http://forums.laravel.io/viewtopic.php?id=16677
I am designing a WCF service that has several functions:
1. ProductDTO GetProduct ( Guid productId )
2. void SetProduct ( ProductDTO product )
3. List<ProductDTO> GetAllProducts()
4. void SetAllProductValues ( int newValue )
These are the operations the Service will support.
I will have a Business Layer (BL) and a Data-Access Layer (DAL).
I will be using LINQ-TO-EF as my ORM to connect to the SQL server tables.
My question is - what exactly should the DAL contain ?
I am asking this question because I have read 2 different books saying different things:
First Approach: the DAL contains only classes needed for data-access layer (if at all). It includes special entities or functions for that.
The EDMX and model file for the LINQ-TO-EF is in a seperate assembly (that is referenced by the BL and the Service Layer).
In this method - the BL contains the actual functions that perform the LINQ queries.
For example : 'GetProduct' will perform the LINQ query to extract data from the DB. So - in this approach - what exactly is supposed to be in the DAL ? Is it empty ?
Second Approach: the DAL contains functions for performing CRUD operations on the DB, meaning - any LINQ-TO-EF queries will be done in the DAL.
So - in this approach - what exactly does the BL do except for maybe some validations ?
Which approach is the correct one and how does that answer my concern of that approach ?
From MSDN:
"All code that is specific to the underlying data source – such as creating a connection to the database, issuing SELECT, INSERT, UPDATE, and DELETE commands, and so on – should be located in the DAL. The presentation layer should not contain any references to such data access code, but should instead make calls into the DAL for any and all data requests. Data Access Layers typically contain methods for accessing the underlying database data. The Northwind database, for example, has Products and Categories tables that record the products for sale and the categories to which they belong. In our DAL we will have methods like:
GetCategories(), which will return information about all of the categories
GetProducts(), which will return information about all of the products
GetProductsByCategoryID(categoryID), which will return all products that belong to a specified category
GetProductByProductID(productID), which will return information about a particular product"
Of course you are always free to choose your own design, but I like to stick with generally accepted practices so my code will likely be acceptable in any shop and understandable to anyone that has to maintain it later...
Anyone suggest me how to handle the following scenario.
I have some Db tables that are using in all of my projects so I am creating all these tables in every database (common tables + project tables). Now I have a common data and business libraries that depend on the common tables, I need to split these table entities into two different libs with a single DbContex.
I am using the dependency injection to pass the db context.
I am using the following Vs tools.
EF 4.1
VS 2010.
Regards,
Hareen.
You can either use inheritance like below or
public class CommonContext:DbContext
{
}
public class ProjectContext:CommonContext
{
}
Composition like this. (The answer I have given for your earlier question
Is is possible to use a Collection such as a Multiset or Array as the foreign key in a database scheme?
Background: A student proposes to use such a construct (don't use a join table for the n:m association) to store the following object structure in a database
public class Person {
String name;
List<Resource> res;
…
}
public class Resource {
int id;
List<Person> prs;
…
}
SQL:2003
IMHO, the student didn't understand relational concepts. I don't know how collection types are implemented in todays databases, but they most probably store them in separate tables.
Edit
If it would be technically possible, I doubt that it would be useful. Consider the query language. Sql is designed for relational structures, I doubt that you could really have the same flexibility and possibilities using collection types. If you had it, you couldn't read it anymore. Consider indexes. etc. etc.
Relational structures are primitive, but very powerful and fast. You can do (almost) everything with them. Collection type are actually not needed, although they may be useful in certain cases. Using collections (for relational stuff) just would be more complex and less pure.
As David pointed out, theory allows attribute values to be of a collection type.
However, in your case, which is just to model n:m relationships (am I right about that), it simply does not apply.
If a Person P1 has associated resources R1 and R2, the row for this person would be like {P1, {R1, R2}}. If that collection-typed column were a foreign key referencing some other table, it would mean that there had to be another table in which a row appeared with the collection value {R1, R2} in some column. Which table would that be in your example ?
Collection-typed attributes are mostly useful if you have a need for dealing with empty collections alongside non-empty ones. There is no relational join in the world that will do its equivalent for you.
Simply put, I would have said no. I don't think that it is possible in SQL2003 and in any case it would couple the code and the database structure too closely. Remember good practice of structuring code so that a change to your database doesn't require a change to your code and vice versa.
As Stefan said you need separate tables for Resource and Person with Foreign Key links to the indexes between them.
So based on the classes shown each table would need 3 coloumns.
You would then obtain your class data by using an appropriate query to the database.
In principle, yes you can implement such a referential constraint. That's assuming your RDBMS allows a suitable type for the set of values. For instance it could be a relation value if relation-valued attributes (RVA) are supported.
If it was a RVA then the constraint could easily be expressed in the relational algebra / calculus or its equivalent. For instance you can do it in a RDBMS like Rel which supports the Tutorial D language. Doing it in SQL is probably going to be a lot harder - but then SQL is not a real relational language.
Of course, the fact that you can do it relationally does not necessarily make it a good idea...
I'm beginning to wonder if I am in fact too dumb to use NHibernate. I'm currently using FluentNHibernate to create simple db mappings and that's worked well for us. When dealing w/ our various classes in isolation, we're able to read and write, perform updates, etc. to all of those classes. My problem however is in trying to build up a query that involves anything more complex than filtering upon fields of the entity type. A perfect example is illustrated below--
The pertinent portions of the mappings:
public class UserMap : ClassMap<User> {
Id(u => u.Id).Column("UserID").GeneratedBy.Identity();
//other non-pertinent fields
}
public class RoleMap : ClassMap<Role> {
Id(r => r.Id).Column("RoleId").GeneratedByIdentity();
//snip
}
public class RoleMapMap : ClassMap<RoleMap> {
Id(rm => rm.Id).Column("RoleMapId").GeneratedByIdentity();
Map(rm => rm.UserId);
Map(rm => rm.RoleId);
//snip
}
The intent is to generate a query w/ the Criteria API to retrieve all users of a specific role--at a high level, filter rolemap based on a specific role ID, then join to Users, and return only those users.
Attempted with following, but my usage of CreateAlias is obviously flawed, as the runtime exception basically tells me that it has no idea what "RoleMap" in the below is as it relates to the User object.
var criteria = session.CreateCriteria<User>().
CreateAlias("RoleMap", "rm").
Add(Expression.Eq("rm.UserId", "UserId")).
Add(Expression.Eq("rm.RoleId", 99)).
SetResultTransformer(new
DistinctRootEntityResultTransformer());
var users = criteria.List<User>();
Can someone point me in the right direction? I'd prefer not to edit the underlying objects to expose collections--(e.g. a User.Roles[] collection) as there's cases where we specifically have tables used solely for joins but we don't want floating to the middle tier. So learning how to join isolated classes is going to matter to us.
Your mapping contains no way to navigate from User to RoleMap, yet that is what you are trying to do in your Criteria API call. You have multiple options. Here are a couple:
1) Allow User to navigate to RoleMap in your mapping. This is the easiest and how it's normally done.
2) Use two queries, one to get a list of UserIds based on the RoleMap to Role relationship and then a second query to get all the Users for those UserIds.
You say you don't want a User.Roles collection in your middle tier, but NHibernate should exist in your data layer, not necessarily your business layer. You can allow NHibernate to know about User.Roles while effectively hiding it from your business layer.
Joining isolated classes isn't really what ORMs are built for. ORMs are built for joining related classes. Related classes are generally mapped to related tables at the database level. To join isolated classes, you are going to need to do things like option 2 above where you run multiple queries and/or work around the lack of a relationship in custom code.