Virtual Objects
This first version of the Scaffold only supports SqlServer.
// Creates all models based on the given data source.
Scaffold Models <SqlServer> <Database>
// Scaffold Switchs to change behavior
-Repository (Creates a Repository layer of abstraction)
-TableName <TableName> (Create the entity model of a single table)
-NoLazyLoad (Doesn't create virtual members)
-ForceAnnotations (Every field gets an annotation)
-DefaultAttributes (Use the default VirtualObjects.Mapping namespace)
-DontConfig (Doesn't change the .Config connection string)
-ModelFolder <FolderName> (By default: Models)
-RepositoryFolder <FolderName> (By default: Repositories)
-AnnotationsFolder <FolderName> (By default: Annotations)
-ToFolder <FolderName> (By default: Scaffolds into a folder)
// Creates the RepositoryLayer
Scaffold Repository
// Scaffold Switchs to change behavior
-ModelFolder <FolderName> (By default: Models)
-RepositoryFolder <FolderName> (By default: Repositories)
-AnnotationsFolder <FolderName> (By default: Annotations)
-ToFolder <FolderName> (By default: Scaffolds into a folder)
// Sets the configuration string
Scaffold Config <ServerName> <DataBase>
-ProviderName (Use a different Provider)
-ConfigName (Change the configuration of the given name)
// Creates the BusinessLayer
Scaffold Business <ModelType>
-ModelFolder <FolderName> (By default: Models)
-BusinessFolder <FolderName> (By default: Business)
-ToFolder <FolderName> (By default: Scaffolds into a folder)
-NoDelete (Business doesnt support delete operations)
-NoInsert (Business doesnt support insert operations)
-NoUpdate (Business doesnt support update operations)
-ReadOnly (Business for read operations only)
public class Employee
{
public String EmployeeId { get; set; }
public String LastName { get; set; }
// Other fields ...
}
<connectionStrings>
<clear/>
<add name="YourMachineName"
providerName="System.Data.SqlClient"
connectionString="
Data Source=.\instance;
Initial Catalog=db;
Integrated Security=true"/>
</connectionStrings>
using (var session = new Session())
{
IQueryable<Employee> employees = session.GetAll<Employee>()
.Where(e => e.BirthDate.Year > 1983);
session.Insert(new Employee
{
Name = "I'm the new guy!"
});
}
There's no need to derive our model types from any specific type. But they can... Our POCO classes should be defined with properties with R/W (get/set).
public int EmployeeId { get; set; }
public String LastName { get; set; }
public String FirstName { get; set; }
//...
In case we want lazy load of a foreign reference the property should be marked as Virtual (to enable interception). This is not a requirement, use it if you would like the ORM to load your references for you.
public virtual Employee ReportsTo { get; set; }
To map with the data source fields attributes can be used to add metadata to our poco classes. This is not a requirement.
This is fully configurable. To configure the way pocos are mapped, you must derive the type SessionConfiguration and override the method ConfigureMappingBuilder(IMappingBuilder builder). The final stage is to give the custom configuration to the Session. See above.
This configuration can be made so our pocos will be totally compatible with EntityFramework or other ORM frameworks/libraries.
class Configuration : SessionConfiguration
{
public override void ConfigureMappingBuilder(IMappingBuilder builder)
{
//
// TableName getters
//
builder.EntityNameFromType(e => e.Name);
builder.EntityNameFromAttribute<TableAttribute>(e => e.TableName);
//
// ColumnName getters
//
builder.ColumnNameFromProperty(e => e.Name);
builder.ColumnNameFromAttribute<ColumnAttribute>(e => e.FieldName);
// (e.g.) A key is a property that ends with 'Id'
// builder.ColumnKeyFromProperty(e => e.Name.EndsWith("Id"));
//
builder.ColumnKeyFromAttribute<KeyAttribute>();
builder.ColumnKeyFromAttribute<IdentityAttribute>();
builder.ColumnIdentityFromAttribute<IdentityAttribute>();
builder.ForeignKeyFromAttribute<AssociationAttribute>(e => e.OtherKey);
}
}
using(var session = new Session(new Configuration())
{
// Use the session with your custom configuration.
}
// Create
Employee Sergio = session.Insert(new Employee
{
FirstName = "Sérgio",
LastName = "Ferreira",
BirthDate = new DateTime(1983, 4, 16)
});
// Read
Employee employee = session.GetById(Employee { EmployeeId = 1 });
// Update
session.Update(employee);
// Delete
session.Delete(employee);
IQueryable<T> query = Session.GetAll<T>();
// Or
IQueryable<T> query = Session.Query<T>();
All queries can be verified under "VirtualObjects.Tests.Queries" namespace.
Just to be clear, all Linq queries are translated into the proper SQL parameterized commands. The framework will only load what needs to be loaded from the data source.
To see the generated SQL just provide (to the session) a configuration instance that sets the Logger to Console.Out (or other) for debug purposes. In release versions your app should never have the logger setted. This could result in pour performance.
// On group joins (full entities and collection load)
from o in Query<Orders>()
join od in Query<OrderDetails>() on o equals od.Order into ods
select new { Order = o, Details = ods }
// On Joins (full entities load)
from o in Query<Orders>()
join od in Query<OrderDetails>() on o equals od.Order
join e in Query<Employee>() on o.Employee equals e
select new { Order = o, Detail = od, Employee = e }
// Specific members projection
from o in Query<Orders>()
join od in Query<OrderDetails>() on o.Freight equals od.UnitPrice
select new { o.OrderId, od.UnitPrice, o.ShipCity }
Query<Employee>().Select(e => new { e.EmployeeId, e.LastName, e.FirstName })
// Agregated Projection
Query<Employee>().GroupBy(e => e.City)
.Select(e => new
{
City = e.Key,
Min = e.Min(o => o.EmployeeId),
Max = e.Max(o => o.EmployeeId),
Sum = e.Sum(o => o.EmployeeId),
Count = e.Count(),
Average = e.Average(o => o.EmployeeId)
})
// Calculated Projection
Query<Employee>().GroupBy(e => e.City)
.Select(e => new
{
Average = e.Sum(o => o.EmployeeId) / (e.Count()*1.0) * 100.0
})
To make entity mapping as fast as possible the framework creates an assembly specific for that entity. This assembly contains helper methods that are used by VirtualObjects to Create instances of that entity without using reflection, enables VO to Map properties given a datareader, and so on.
Checkout the microsoft table at ADO.Net
If you have any suggestions for this project or something is not working right please contact me at Alien.Software.Engineer@gmail.com or @AlienEngineer (github)
PM> Install-Package VirtualObjects