henkmollema / Dommel

CRUD operations with Dapper made simple.
MIT License
634 stars 100 forks source link

ForeignKeyPropertyResolver improvements to allow for custom relationships #171

Closed TroySchmidt closed 4 years ago

TroySchmidt commented 4 years ago

If the interface IForeignKeyPropertyResolver computed the automatic multimapping join statement, then a later improvement to FluentMapping for custom foreign key resolution could include custom join statements templates. There are definite use case needs for needing multiple columns in the join statements of relationships including composite keys.

henkmollema commented 4 years ago

I'm not sure which use case this will enable. Do you have an example?

TroySchmidt commented 4 years ago

The default expression tree relationship.

Expression<Func<Parent, Child, bool>> defaultRelationship = (p, c) => p.ChildId == c.Id

But there are times that more keys are necessary in the join relationship. This can be either for composite keys or just for SQL querying performance and indices usage.

Expression<Func<Parent, Child, bool>> defaultRelationship = (p, c) => p.ChildId == c.Id && p.OtherKeyId == c.OtherKeyId

So if the IForeignKeyPropertyResolver returned an Expression instead of just the key then custom implementations of ForeignKeyPropertyResolver and \ or Fluently mapped join definitions could provide richer Expression trees to define the join to be used.

I am currently working in our fork on a new SqlQuery class that would replace SqlExpression. I only had to make one improvement in the expression tree visitation in order to have it output the SQL from the above expressions. When it gets down to parameter resolution, if it is a property and not a resolvable value then it returns the property string and not just the DynamicParameter as it does now.

henkmollema commented 4 years ago

I'm still unsure what "default expression tree relationship" means. Is this a concept of "FluentMapping"? I don't know what that is either. 😄

Also, the foreign key property resolver is not expression-based but reflection-based. How would that work?

TroySchmidt commented 4 years ago

I am proposing that instead of the current mechanisms that return a property instead return an Expression tree of the relationship. Then that would allow for this increased flexibility on determining the join in more complex ways.

It would be something along the lines of adding the below logic into the default property resolver. This also has one tiny improvement to the VisitExpression methods that I copied out from the SqlExpression class. This would leverage the existing VisitExpression code. Entity Framework has a more verbose fluent mapping API of HasOne().ForeignKey() etc. Given the usage of this for custom joins as well as defining fluent mapped relationships this expression tree method gives flexibility for both. Link to improvements

TroySchmidt commented 4 years ago

Updated my example class to latest master changes. Updated file

henkmollema commented 4 years ago

I don't think this is something I want in the Dommel core library.