Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Added support for filling properties not defined in model #83

Merged
merged 4 commits into from
May 26, 2021

Conversation

esentio
Copy link
Owner

@esentio esentio commented May 26, 2021

This PR fixes #33.

This allows to fill entity properties not defined in model in SELECT queries using Include methods.

For example:

using (var db = CreateContext())
{
    var list = db.From<Article>()
                 .SelectAll()
                 .Include(x => x.PriceWithDiscount, x => x.Price * 0.9m)
                 .ToList();
}

There will be a new column in SQL resultset with Price * 0.9 value and this value will be assigned to Article.PriceWithDiscount property.

VB.NET even allows to use nicer assignment syntax:

Using db = CreateDbContext()
  Dim list = db.From(Of Article).
                SelectAll().
                Include(Sub(x) x.PriceWithDiscount = x.Price * 0.9D).
                ToList()
End Using

Every expression used in Include method will be added as an additional column (or multiple columns) to the SELECT statement. If you don't need columns automatically added by SelectAll method, you need to exclude them:

// Exclude ArticleCategory columns to make GROUP BY work:
using (var db = CreateContext())
{
    var list = db.From<Category>()
                 .LeftJoin<ArticleCategory>(j => j.T1.Id == j.T2.CategoryId)
                 .GroupBy(j => j.T1)
                 .SelectAll()
                 .ExcludeT2()
                 .Include(j => j.T1.ArticleCount, j => Yamo.Sql.Aggregate.Count(j.T2.ArticleId))
                 .ToList();
}
// Assuming: modelBuilder.Entity<Article>().HasOne(x => x.Label);
// Exclude Label columns to not create Label object and to not assign it to Article.Label property.
// Only Article columns and Label.Description column will be in the resultset.
using (var db = CreateContext())
{
    var list = db.From<Article>()
                 .LeftJoin<Label>(j => j.T1.Id == j.T2.Id)
                 .SelectAll()
                 .ExcludeT2()
                 .Include(j => j.T1.LabelDescription, j => j.T2.Description)
                 .ToList();
}
// If ExcludeT2() were not called, Label columns would be included twice (and Article.Label property would be filled).
using (var db = CreateContext())
{
    var list = db.From<Article>()
                 .LeftJoin<Label>(j => j.T1.Id == j.T2.Id)
                 .SelectAll()
                 .ExcludeT2()
                 .Include(j => j.T1.Tag, j => j.T2)
                 .ToList();
}

You can include simple scalar values like, whole entity (model object), ValueTuple (although only VB.NET supports this) and anonymous objects (probably useful only in limited number of use cases due to casting issues).

NOTE: if whole entity is included, it's always a "detached copy" unrelated to what would normally work using SelectAll method. This means:

  • any Exclude method on that entity is ignored for Include entity instance (it always contains all columns defined in model configuration)
  • no relationships are set for Include entity instance
  • Include entity instance is not used in any relationship

If you don't need a "detached copy", it's probably just better to use As method to define an ad hoc relationship.

NOTE: Include is only available "in automatic mode", i.e. when SelectAll() is used. It's not supported in custom selects, i.e. when Select(<expression>) is used!

@esentio esentio merged commit e1ef140 into master May 26, 2021
@esentio esentio deleted the feature/include branch May 26, 2021 19:41
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Set entity properties not defined in model
1 participant