ASP MVC Lambda Expressions or Query Extensions? - sql

I am using a Model Factory to query the related entities from requesting model.
The result is a ViewModel from a given entity.
Get Data
var posts = _postRepo.GetCommunityPosts(Id); // get an iqueryable
ICollection<PostViewModel> result = await ModelFactory.PostFactory(posts, take, skip); //using the ModelFactory to create the viewmodel
Process Data
public async Task<ICollection<PostViewModel>> PostFactory(IQueryable<TRDPost> posts)
{
return await posts.Select(a => new PostViewModel //the viewmodel
{
// simple properties
Created = a.Created,
Body = a.Body,
Id = a.Id,
// related viewmodels
Member = new MemberViewModel
{
// Member related stuff here
// a lot of properties and also related viewmodels here
}
}
}).ToListAsync<PostViewModel>();
The Question
Having a lot of different Factories which all have the "Member" View Model. This is really a bad style because I have tons code redundancy. Is there a way to execute a function in the query, e.g.:
public async Task<ICollection<PostViewModel>> PostFactory(IQueryable<TRDPost> posts)
{
return await posts.Select(a => new PostViewModel //the viewmodel
{
// simple properties
Created = a.Created,
Body = a.Body,
Id = a.Id,
// related viewmodels
Member = GetMemberViewModel(a) // is this possible?
}
}).ToListAsync<PostViewModel>();
Read a lot about Expressions all I tried was without success. It would be nice if you point me into the right direction.

Thanks to Tomas Petricek who said this worth words:
Declaration of lambda expression that will be used by the query is
straightforward, because it isn't different than any other C# lambda
expressions. The query is more interesting because it uses two
extension different methods. First method called ToExpandable creates
a thin wrapper around the DLINQ Table object. Thanks to this wrapper
you can use second method called Invoke that extends the Expression
class to invoke the lambda expression while making it still possible
to translate query to T-SQL. This works because when converting to the
expression tree, the wrapper replaces all occurrences of Invoke method
by expression trees of the invoked lambda expression and passes these
expressions to DLINQ that is able to translate the expanded query to
T-SQL.
And reading this article must be helpful: http://tomasp.net/blog/linq-expand.aspx/

Related

Kotlin field Assignment via Scope Function (Apply )

What is the difference between two such field assignments? Actually, the first way seems very readable but I come across second way in many code samples.
Is there a special reason?
class Login {
var grantToken = GrantTokenRequest()
fun schema(schema: String) {
this.grantToken.schema = schema
}
}
class Login {
var grantToken = GrantTokenRequest()
fun schema(schema: String) = apply { this.grantToken.schema = schema }
}
The difference is the return type of the function schema.
The first way returns Unit.
The second way returns the type of what this is in the current scope.
In your case the second way will return the Login type, so the instance of this class.
The second approach is just more idiomatic in cases when you are "configuring an object". From Kotlin docs about apply
The common case for apply is the object configuration. Such calls can be read as “apply the following assignments to the object [and return the object itself].”
One reason why the second approach is useful, is because it makes call chaining possible. The general term for this kind of "return this" method chaining is "fluent interface".
val login = Login()
.schema("...")
.anotherFunctionOnLoginClass(...)
.moreCallChaining(...)
An additional note: The this used inside the apply lambda is not needed, because apply already sets this as the Receiver. The code could be simplified to
fun schema(schema: String) = apply { grantToken.schema = schema }

Single responsibility principle in API

Please have a look at following piece of code:
public interface ICultureService
{
List<Culture> GetCultures();
bool IsCultureSupported(Culture culture);
Culture GetFallbackCulture();
}
We found that most of the consumers first call IsCultureSupported to validate if their culture is supported or not. And if culture is not supported, they call GetFallbackCulture():
public CallingMethod()
{
if(!cultureManager.IsCultureSupported(currentCulture))
{
currentCulture=cultureManager.GetFallbackCulture();
}
.
.
.
}
As per Single Responsibility Principle (and other OOPs rules), is it ok to introduce a function (in ICultureService and its implementation) like:
function GetFallbackCultureIfInvalid(Culture culture)
{
if(this.IsCultureSupported(culture)
{
return this.FallbackCulture();
}
}
As per Single Responsibility Principle (and other OOPs rules), is it ok to introduce a function (in CultureManager) like:
What you are referring to is called the Tell-Don't-Ask principle rather than the Single Responsibility Principle. Adding the GetFallbackCultureIfInvalid function actually makes the client code more readable. You should also reduce the visibility of the IsCultureSupported so that this method is no longer visible to the client code.
That said, it looks like CultureManager is an implementation of CultureService so it doesn't make sense to add a new method named GetFallbackCultureIfInvalid in CultureManager which is not a part of CultureService interface. What you should do is stick to a single method called GetFallbackCulture in CultureManager and let it return a fall back culture if the required condition is met :
Culture GetFallbackCulture(Culture culture) {
Culture fallBackCulture = culture;
if(!this.IsCultureSupported(culture) {
fallBackCulture = this.FallbackCulture();
}
return fallBackCulture;
}

Perform an overload resolution programmatically

Is there a way to use either System.CodeDom or the Roslyn API to resolve an overloaded method call from code? At runtime, I have a method name and a list of parameters, I want to find the method the compiler would have picked at compile time.
As #SLaks and #just.another.programmer suggested it is possible to exploit C# dynamic infrastructure. But it's really not straightforward nor simple. I was gazing into decompiled code for couple of hours to find following magic code. And I don't understand it completely. In the first step Binder class is created, with parameter options set to use compile time types.
In the second magic step, the binder is called with the actual parameters. Each parameter has its value (null, its not used when UseCompileTimeType is set) and their expression. If you know types instead of expression, use Expression.Parameter(yourType) to substitute them.
public static Expression GetInvokeMemberExpression(Expression expr, string name, Expression[] arguments)
{
var type = expr.Type;
var argTypes = arguments.Select(e => e.Type).ToArray();
// do magic #1
var binder = (DynamicMetaObjectBinder)Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
CSharpBinderFlags.None, name,
Type.EmptyTypes, // type arguments
typeof(object),
Enumerable.Repeat(0, argTypes.Length + 1).Select(_ => CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null)).ToArray());
// do magic #2
var result = binder.Bind(DynamicMetaObject.Create(null, expr), arguments.Select(a => DynamicMetaObject.Create(null, a)).ToArray());
var resultMethodCall = (result.Expression as UnaryExpression).Operand as MethodCallExpression; // unwrap convert to ebject expression
var method = resultMethodCall.Method;
return resultMethodCall;
}
I was trying similar piece of code in DotVVM framework, but I haven't found a way how to "inject" custom implicit conversions, so I wrote a simple method overload recognition function. But we are still using dynamic for operators. You can find the code on github

mimicking MVC DisplayExtensions methods (fun and confusion with lambdas)

I'm trying to develop my own editable data grid for MVC in a fluent interface usable in a View. My question is really about using lambdas, not about data grids, but the context might help for understanding my question. Anyway, I have some code that looks like this:
#model IEnumerable<AdamOneilSoftware.Models.Something>
#{
var firstItem = Model.FirstOrDefault();
}
#(Html.DataGrid(Model)
.CssClass("data")
.TextBox(model => firstItem.Text)
.TextBox(model => firstItem.Position)
.Render())
This much compiles okay. You can see that I want to use lambdas to setting up columns of my data grid. The thing I don't understand is how to do anything with those lambdas in my data grid class. I have surmised that I need to compile/invoke the expression, but I'm stuck on the Invoke part. Here's what I have:
public DataGridBuilder<TModel> TextBox<TValue>(Expression<Func<TModel, TValue>> expression)
{
var del = expression.Compile();
// invoke the delegate?
var result = del.Invoke(); // but this expects a TModel argument
return this;
}
The Invoke call expects a TModel argument (according to the Func declaration -- I understand that). But this doesn't work--and rightly so:
var result = del.Invoke(TModel);
How do I form the TModel argument in the Invoke call? Or am I heading the wrong direction completely? The goal is to do something like what the DisplayFor and EditorFor methods do--render some HTML with some awareness of the target property's metadata (DataFormatString, Display label, and so on).
You need to get the view's Model instance to pass as the parameter.
You can find that in Html.ViewData.Model.

Best practice for returning IEnumerables from LINQ Methods

OK,
This question has probably been answered before, but I'm not sure of how to word the Title.
I have a class that has methods which return many composite LINQ queries. Most of these queries form Anonymous Types in order to get the data I need. I found out that I'm not able to return an Anonymous Type from a method, so I've been creating sub classes and populating them in the "select new" part of the query.
Is there a better way of doing this? All of these methods return an IEnumerable of some kind and I really want to keep things extracted.
Thanks!
You could explictly define the anonymous types you are using as classes, and instead return those classes.
Generally if you are writing a library for others to consume, explicitly defined classes are a best practice.
or you can use technic of dp in this post
// Useful? probably not.
private void foo()
{
var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}
object GetUserTuple()
{
return new { Name = "dp", Badges = 5 };
}
// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T type)
{
return (T) obj;
}