Marr DataMapper provides a fast and easy to use wrapper around ADO.NET that enables you to focus more on your data access queries without having to write plumbing code.
Load one-to-one, one-to-many, and inherited entity models with ease. No special base class required.
Learn more:
documentationNuGet:
https://nuget.org/packages/MarrDataMapper
Highlights
- Lazy loaded relationships defined using expressive Linq syntax:
public void CreateMappings()
{
MapBuilder builder = new MapBuilder();
builder.BuildColumnsFromSimpleTypes<Order>()
.For(b => b.ID).SetPrimaryKey();
builder.Relationships<Order>()
.For("_orderItems").LazyLoad((db, order) =>
db.Query<OrderItem>().Where(oi => oi.OrderID == order.ID).ToList());
builder.BuildColumnsFromSimpleTypes<OrderItem>();
}
- Linq syntax for easy parameterized querying with ORM capabilities:
List<Person> people = db.Query<Person>().Where(p => p.Age >= 18);
- Custom query builder makes it easy to dynamically append where conditions:
List<Person> people = db.Query<Person>()
.Where(p => p.Name == "Bob" || p.Name == "Robert")
.AndWhere("([Age] = 35)")
.OrderBy(p => p.Name);
// Generates a query with the following where clause:
"WHERE ([t0].[Name] = @P0 OR [t0].[Name] = @P1) AND ([Age] = 35)"
- Convenient syntax for querying simple lists of primitive data types
List<string> names = db.Query<string>("SELECT FirstName + ' ' + LastName FROM PersonTbl");
- Can easily access the DataReader directly if needed:
List<Person> people = db.ExecuteReader(
"SELECT * FROM tblPerson",
r => new Person { ID = r.GetInt32(0), Name = r.GetString(1) }
);
- Can translate unnormalized query data (like a view) into a multilayered object graph by using the .Graph() method, or by using the QueryToGraph method:
List<Person> people = db.Query<Person>()
.Graph()
.Where(p => p.Age >= 18);
or
List<Person> people = db.QueryToGraph<Person>("SELECT * FROM Person WHERE Age >= 18");
- Paging is supported for SQL Server 2005 and higher:
int pageNumber = 1;
int pageSize = 20;
var results = db.Query<Company>()
.OrderBy(c => c.Name)
.Page(pageNumber, pageSize)
.ToList();
or using standard linq paging syntax
int pageNumber = 1;
int pageSize = 20;
var results = db.Query<Company>()
.OrderBy(c => c.Name)
.Skip(pageNumber - 1)
.Take(pageSize)
.ToList();
List<Message> messages = UoW.DB.Query<Message>()
.Where(m => m.ToUser == recipient)
.OrderByDescending(m => m.SentOn)
.Page(pageNumber, pageSize)
.ToList();
int totalRecords = UoW.DB.Query<Message>()
.Where(m => m.ToUser == recipient)
.GetRowCount();
- Testable Interface driven design
IDataMapper db = MockRepository.GenerateMock<IDataMapper>();
var queryBuilder = MockRepository.GenerateMock<QueryBuilder<Product>>();
var sortBuilder = MockRepository.GenerateMock<SortBuilder<Product>>();
queryBuilder.Expect(b => b.Where("")).IgnoreArguments().Return(sortBuilder);
sortBuilder.Expect(b => b.ToList()).Return(new List<Product> {
new Product { ID = 18, Name = "Product18" },
new Product { ID = 19, Name = "Product19" },
new Product { ID = 20, Name = "Product20" }
});
db.Expect(d => d.Query<Product>()).Return(queryBuilder);
- Fluent syntax for creating object / data mappings via code
public void InitMappings()
{
MapBuilder builder = new MapBuilder();
builder.BuildTable<Person>("PersonTable");
builder.BuildColumns<Person>()
.For(p => p.ID)
.SetPrimaryKey()
.SetReturnValue()
.SetAutoIncrement();
builder.BuildRelationships<Person>();
builder.BuildColumns<Pet>()
.For(p => p.ID)
.SetPrimaryKey()
.SetAltName("Pet_ID")
.For(p => p.Name)
.SetAltName("Pet_Name");
}
- Can also declare object / data mappings using attributes
[Table("PersonTable")]
public class Person
{
[Column("First_Name"]
public string FirstName { get; set; }
[Column] // Uses property name by default
public string Description { get; set; }
}
- Easy instantiation of the DataMapper:
protected IDataMapper CreateDB()
{
IDataMapper db = new DataMapper(
System.Data.SqlClient.SqlClientFactory.Instance,
"[db connection string goes here]");
db.SqlMode = SqlModes.Text;
return db;
}
- MDM uses a FastReflection library that uses caching in conjunction with reflection to provide very fast results
- MDM can also work in medium trust environments (ie GoDaddy) using the optional "SimpleReflectionStrategy"
Learn more:
documentation