Packages in this repository include abstractions for mapping LINQ expresions and objects between business and data objects types.
- Maps business model objects to and from data objects.
- Maps query expressions from business model to data model.
To use:
//Create a context
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
}
//Create Store
public interface ISchoolStore : IStore
{
}
public class SchoolStore : StoreBase, ISchoolStore
{
public SchoolStore(SchoolContext context)
: base(context)
{
}
}
//Create Repository
public interface ISchoolRepository : IContextRepository
{
}
public class SchoolRepository : ContextRepositoryBase, ISchoolRepository
{
public SchoolRepository(ISchoolStore store, IMapper mapper) : base(store, mapper)
{
}
}
//Register Services including AutoMapper profiles.
IServiceProvider serviceProvider = new ServiceCollection()
.AddDbContext<SchoolContext>
(
options =>
{
options.UseInMemoryDatabase("ContosoUniVersity");
options.UseInternalServiceProvider(new ServiceCollection().AddEntityFrameworkInMemoryDatabase().BuildServiceProvider());
}
)
.AddTransient<ISchoolStore, SchoolStore>()
.AddTransient<ISchoolRepository, SchoolRepository>()
.AddSingleton<AutoMapper.IConfigurationProvider>(new MapperConfiguration(cfg => cfg.AddProfiles(typeof(SchoolProfile).GetTypeInfo().Assembly)))
.AddTransient<IMapper>(sp => new Mapper(sp.GetRequiredService<AutoMapper.IConfigurationProvider>(), sp.GetService))
.BuildServiceProvider();
//Call the repository
ISchoolRepository repository = serviceProvider.GetRequiredService<ISchoolRepository>();
ICollection<StudentModel> list = Task.Run(() => repository.GetItemsAsync<StudentModel, Student>()).Result;
Create complex expressions from single descriptor objects.
To use:
public void BuildFilter()
{
IConfigurationProvider config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ExpressionOperatorsMappingProfile>();
});
IMapper mapper = config.CreateMapper();
Expression<Func<Product, bool>> filter = GetFilterExpression<Product>
(
//$it => $it.AlternateAddresses.Any(address => (address.City == "Redmond"))
new FilterLambdaDescriptor
(
new AnyDescriptor
(
new MemberSelectorDescriptor("AlternateAddresses", new ParameterDescriptor("$it")),
new EqualsBinaryDescriptor
(
new MemberSelectorDescriptor("City", new ParameterDescriptor("address")),
new ConstantDescriptor("Redmond")
),
"address"
),
typeof(Product),
"$it"
)
);
Expression<Func<T, bool>> GetFilterExpression<T>(FilterLambdaDescriptor descriptor)
=> (Expression<Func<T, bool>>)mapper.Map<FilterLambdaOperator>
(
descriptor,
opts => opts.Items["parameters"] = new Dictionary<string, ParameterExpression>()
).Build();
}
public void BuildSelector()
{
IConfigurationProvider config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ExpressionOperatorsMappingProfile>();
});
IMapper mapper = config.CreateMapper();
Expression<Func<IQueryable<Category>, Category>> selector = GetSelectorExpression<IQueryable<Category>, Category>
(
//$it => $it.FirstOrDefault(a => (a.CategoryID == -1))
new SelectorLambdaDescriptor
(
new FirstOrDefaultDescriptor
(
new ParameterDescriptor("$it"),
new EqualsBinaryDescriptor
(
new MemberSelectorDescriptor("CategoryID", new ParameterDescriptor("a")),
new ConstantDescriptor(-1)
),
"a"
),
typeof(IQueryable<Category>),
typeof(Category),
"$it"
)
);
Expression<Func<T, TResult>> GetSelectorExpression<T, TResult>(SelectorLambdaDescriptor descriptor)
=> (Expression<Func<T, TResult>>)mapper.Map<SelectorLambdaOperator>
(
descriptor,
opts => opts.Items["parameters"] = new Dictionary<string, ParameterExpression>()
).Build();
}
ExpressionOperatorsMappingProfile
is a mapping profile from LogicBuilder.EntityFrameworkCore.SqlServer
.
For serializable descriptors, replace cfg.AddProfile<ExpressionOperatorsMappingProfile>();
with a custom mapping profile with serializable descriptors.