Working with database views

Views are one of the ways of putting related data from multiple tables under one container. If you have been using any mainstream RDMBS for some time, then it is possible that you have come across a view more than once. If not, a view is a simple SQL script where you specify which columns from which tables you want to appear in the view, and how those tables are related with each other. Once that script is executed, the database will create an object that holds information about the tables and columns involved in the view definition. After that, you can use the view like any other table with only one restriction; that you are only allowed to read from the view. You cannot update the data in the view (some RDBMS allows the updating of part of the data in a view, with some constraints, but let's ignore that for a moment). Reason for this is that, when you execute a SELECT statement against a view, the database server actually runs the original script that we used to build the view, and then applies the SELECT statement on the result of running the view scripts.

Note

Internally, how SELECTs against views are executed can be different. Every RDMBS would have its own logic to run it, and it is more detailed than what was described in the previous few lines. But at a very high level, that is how views work.

If you are working on an application that reads data from a legacy database but never writes back, then see if you can make use of views to get a matching database schema for your domain model. You do not have to use this strategy for the whole domain model. You can use it for part of the domain model, or even a single entity. Let's take a look at an example. We will use the same example that we used for joins earlier. In our domain, we have an Employee class which looks as follows:

public class Employee
{
  public virtual int Id { get; set; }
  public virtual string Firstname { get; set; }
  public virtual string Lastname { get; set; }
  public virtual DateTime DateOfJoining { get; set; }
  public virtual string AddressLine1 { get; set; }
  public virtual string AddressLine2 { get; set; }

}

Again, the situation in the database is similar to what we had with the join. We have an Employee table and an Address table. Since we only want to load the Employee entity and never insert or update it, we should decide to create a view to match our entity definition. Following is how that view could look:

CREATE VIEW [dbo].[EmployeeView]
AS
SELECT dbo.Employee.Id,
dbo.Employee.Firstname,
dbo.Employee.Lastname,
dbo.Employee.DateOfJoining,
dbo.Address.AddressLine1,
dbo.Address.AddressLine2
FROM dbo.Address INNER JOIN
dbo.Employee ON dbo.Address.Employee_Id = dbo.Employee.Id

The preceding view is just joining the Employee and Address tables, to return data combined from both tables. Once this view is in place, we can treat it like a table from an NHibernate point of view and map it just like that. The following code snippet shows the mapping for this view:

public class EmployeeMapping : ClassMapping<Employee>
{
  public EmployeeMapping()
  {
    Table("EmployeeView");
    Id(e => e.Id);
    Property(e => e.Firstname);
    Property(e => e.Lastname);
    Property(e => e.DateOfJoining);
    Property(e => e.AddressLine1);
    Property(e => e.AddressLine2);
  }
}

And we are done. This is exactly the same as mapping a usual table. The only additional thing is declaring a table name. Because view name is not the same as entity name, we need to tell NHibernate what the name of the table to which we want to map this entity is. As long as we only query the Employee entity and do not try to save or update it, this would work just fine. We can even mark the entity as read-only by adding the following lines of code to the mapping file:

public class EmployeeMapping : ClassMapping<Employee>
{
  public EmployeeMapping()
  {
    Mutable(false);
    //other mapping configuration
  }
}

This code will throw an exception when we try to modify the entity state. Even without the preceding code, we will get an exception when we try to update the entity, but for a read-only entity the exception will be thrown by NHibernate without hitting the database. Remember that we could still save a transient instance of the read-only entity. In that case, NHibernate would hit the database and come back with an error from database server that a record cannot be inserted in a view.

Before we close this topic, note that a view is a simple SELECT statement, at the end of the day. While defining a view you can use almost every SQL construct that is valid in a SELECT statement. So, if you want to sort or filter records within the definition of a view, you can do so.

Note

This example is very close to the example we used during join. This may give you the impression that views can be substituted in situations where join is used. This is true, but the reverse is not true. There would be situations where you could use views but not joins. We used a familiar example to keep the discussion light. Do not mix these two concepts up. They stand on their own.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset