Skip to content

andy-clymer/LogicBuilder.DataComponents

 
 

Repository files navigation

LogicBuilder.DataComponents

Packages in this repository include abstractions for mapping LINQ expresions and objects between business and data objects types.

LogicBuilder.EntityFrameworkCore.SqlServer

  • 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;

Build LINQ Expressions Dynamically

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.

About

Contains abstractions for transferring business model objects to and from data objects and SQL Server.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 99.6%
  • PowerShell 0.4%