Moq returns values based on arguments - .net-core

need small help about returning values based on arguments.
Setup of mocking contains expressions like
mockingObject
.Setup(_=>_.Select(It.IsAny<Expression<Func<Entity, bool>>>(),
It.IsAny<Func<IQueryable<Entity>, IOrderedQueryable<Entity>>>(),
It.IsAny<List<Expression<Func<Entity, object>>>>(), It.IsAny<int?>(), It.IsAny<int?>())))
.ReturnsAsync((Expression<Func<Entity,bool>>,Func<IQueryable<Entity>, IOrderedQueryable<Entity>>,List<Expression<Func<Entity,object>>>,int, int,EntityList());
But I'm getting error that Expression<Func<Entity,bool>> is a type which is not valid give context.
How should I manage Returns?
Need to mock:
public async Task<Result> UpdateNetworkStatus(string id, NetworkStatus status)
{
var network = _unitOfWork.NetworkRepository.SelectListAsync(x => x.Id == id).Result.FirstOrDefault();
if (network == null)
throw new Exception(nameof(network));
network.Status = status;
_unitOfWork.NetworkRepository.Update(network);
var saved = await _unitOfWork.Commit();
if (!saved)
return Result.Failure(new List<string>
{
"Failed to save"
});
return Result.Success();
}
Here I need to mock all possible scenarios.

Here is the example how I had manage to pass args to returns
unitOfWorkMock.Setup(_ => _.EntityRepository.SelectListAsync(It.IsAny<Expression<Func<Entity, bool>>>(),
It.IsAny<Func<IQueryable<Entity>, IOrderedQueryable<Entity>>>(),
It.IsAny<List<Expression<Func<Entity, object>>>>(), It.IsAny<int?>(), It.IsAny<int?>()))
.ReturnsAsync((Expression<Func<Entity, bool>> filter, Func<IQueryable<Entity>, IOrderedQueryable<Entity>> orderBy, List<Expression<Func<Entity, object>>> includes, int? page, int? pageSize) =>
{
if (filter == null)
return Entities();
return Entities().AsQueryable().Where(filter).ToList();
});

Related

How to build where predicate in EF Core in which the property selected is dynamic

I'm struggling with expression trees and Entity Framework Core.
I have a method that returns an expression tree that I will use for filtering, something like:
public Expression<Func<E, bool>> GetWherePredicate<E>(Func<E, NpgsqlTsVector> selector, string queryText)
{
return entity => selector(entity).Matches(queryText);
}
And then I'd like to invoke this method with something like:
query = query.Where(GetWherePredicate<MyEntity>(i => i.MySearchField, "the_query"));
This produces an error, something like:
System.InvalidOperationException: The LINQ expression 'DbSet()
.Where(i => Invoke(__selector_0, i)
.Matches(__queryText_1))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
While I understand why this doesn't work, I am not sure how to solve this, but suspect it has to do with using expression trees. I thought of creating a new function that has the following signature, something like:
Expression<Func<E, bool>> GetWherePredicate<E>(MemberExpression selectorForSearchField, string queryText);
But I am not able to figure out how to take that expression and apply the Matches function.
Any help is appreciated.
Thanks,
Eric
The following is a way to answer the question, but it is not as simple as I would like. Or more correctly, my intuition tells me there is a cleaner and simpler approach.
My (not so simple) approach is the following:
Create a function that takes a MemberExpression (not a function which selects the property) that looks something like the following:
public Expression<Func<E, bool>> GetWherePredicate<E>(
MemberExpression member,
string queryText)
{
// Get the parameter from the member
var parameter = GetParameterExpression(member);
// Convert the query text into a constant expression
var queryTextExpression = Expression.Constant(queryText, typeof(string));
// Create an expression for the matches function
ftsMatchesFunction = typeof(NpgsqlFullTextSearchLinqExtensions).GetMethod("Matches",
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
null,
new[] { typeof(NpgsqlTsVector), typeof(NpgsqlTsQuery) },
null);
var matchesExpression = Expression.Call(ftsMatchesFunction, member, partialSearchExpression);
return Expression.Lambda<Func<E, bool>>(matchesExpression, parameter);
}
And then to add the predicate, I have something like:
var predicate = PredicateBuilder.New<MyEntity>(false);
var myEntity= Expression.Parameter(typeof(MyEntity), "e");
var childEntity= Expression.PropertyOrField(myEntity, nameof(Invoice.Child));
var searchProperty = Expression.PropertyOrField(childEntity, nameof(Child.FtsSearchVector));
predicate = predicate.Or(_context.GetWherePredicate<MyEntity>(
searchProperty,
"the_query_text"));
And finally to add the filter to the query:
query = query.Where(predicate);
The cleaner or simpler solution is one in which does not need Expression Trees, as the only reason expression trees are needed is because I am not able to figure out how to select the search property in a way that ef can understand.
how to use the predicate to create an expression for retrieving objects from a list.
Method 1
Use the Predicate<generic> type and IEnumerable
[Fact]
public async Task TestPredicate()
{
List<Product> products = new List<Product>
{
new Product {ProductID=1,Name="Kayak",Category="Watersports",Price=275m},
new Product {ProductID=2,Name="Lifejacket", Category="Watersports",Price=48.95m},
new Product {ProductID=3,Name="Soccer Ball", Category="Soccer",Price=19.50m},
new Product {ProductID=4,Name="Corner Flag", Category="Soccer",Price=34.95m}
};
Predicate<Product> predicate = x => x.ProductID==4;
var query=Enumerable.FirstOrDefault(products,x=>predicate(x));
if (query != null) {
output.WriteLine(query.Name);
Assert.True(true);
}
}
Method 2
use Expression<Func pattern for your predicate:
Expression<Func<TimeAndAttendancePunchIn, bool>> predicate = e => e.EmployeeId == employeeId;
PageListViewContainer<TimeAndAttendancePunchInView> container = await taMod.TimeAndAttendance.Query().GetViewsByPage(predicate, order, pageSize, pageNumber);
public async Task<PageListViewContainer<TimeAndAttendancePunchInView>> GetViewsByPage(Expression<Func<TimeAndAttendancePunchIn, bool>> predicate, Expression<Func<TimeAndAttendancePunchIn, object>> order, int pageSize, int pageNumber)
{
var query = _unitOfWork.timeAndAttendanceRepository.GetEntitiesByExpression(predicate);
query = query.OrderByDescending(order).Select(e => e);
IPagedList<TimeAndAttendancePunchIn> list = await query.ToPagedListAsync(pageNumber, pageSize);
repository
public IQueryable<TimeAndAttendancePunchIn> GetEntitiesByExpression(Expression<Func<TimeAndAttendancePunchIn, bool>> predicate)
{
var result = _dbContext.Set<TimeAndAttendancePunchIn>().Where(predicate);
return result;
}

Can we compare two java collections with dynamic equals method?

Lets say we have a 'Client' object:
(am just mentioning the attributes and the equals method alone of the 'Client' object below!!)
public class Client {
private Long clientId;
private String clientName;
private Integer status;
//getters and setters for above attributes
.....
...
//hashCode method
....
..
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Client other = (Client) obj;
if (clientId == null) {
if (other.clientId != null)
return false;
} else if (!clientId.equals(other.clientId))
return false;
if (clientName == null) {
if (other.clientName != null)
return false;
} else if (!clientName.equals(other.clientName))
return false;
if (status == null) {
if (other.status != null)
return false;
} else if (!status.equals(other.status))
return false;
return true;
}
}
From the above equals method itz clear that 'two' client objects are said to be equal if all the attributes of the two objects are identical.
Now assume a scenario where I need to compare two collections(named say incomingClients and existingClients) of Client objects.
The first collection(Collection incomingClients) was generated after reading the 'client' data from a csv/xls file.
The second collection(Collection existingClients) contains, all the existing clients currently in the system.
I can do the following code (using apache CollectionUtils)to get the 'common' clients.
Collection<Client> commonClients = (Collection<Client>)CollectionUtils.intersection(incomingClients,existingClients);
Now with the below code I can remove these commonClients from both the collections.
incomingClients.removeAll(commonClients);
existingClients.removeAll(commonClients);
The intention of removing the 'common clients objects' was that, we dont need to do 'any processing' for these records,
as we are really not at all interested in those records.
Now how can I figure out which are the entirely 'new clients' in the 'Collection incomingClients' collection?
(When I say 'new' it means a client having a new 'clientId' which doesnt exist in the 'Collection existingClients')
Also, how can I figure out which are the clients which needs 'modification'
(When I say 'modification' it means that the 'Collection incomingClients' and Collection existingClients'
have the same clientId, but, say, different 'clientName')
I know that we can do the normal 'for' loop('check below') to figure out the 'new'/'modification needed' clients.
But I thought of writing 'something new', whether we can achieve this using some classes/function in the 'Apache CollectionUtils' package.
Collection<Client> newClients = new ArrayList<Client>();
Collection<Client> toBeModifiedClients = new ArrayList<Client>();
boolean foundClient = false;
Client client = null;
for(Client incomingClient :incomingClients){
foundClient = false;
for(Client existingClient : existingClients){
if(existingClient.getClientId().equals(incomingClient.getClientId())){
client = existingClient;
foundClient = true;
break;
}
}
if(foundClient){
toBeModifiedClients.add(client);
}else{
//not found in existing. so this is completely new
newClients.add(incomingClient);
}
}
Am I 'complicating' a simple stuff??
Any thoughts??
First, yes, you are complicating "simple stuff". Your entire question could be summarized as follows:
Given collections A and B, how can I get the following using CollectionUtils:
A-B, using a particular function that determines equality
A∩B, using a particular function that determines equality
So, yes. CollectionUtils has what you need. Look at CollectionUtils.select().

Get variable name from InArgument

I have a custom activity where the user selects a variable from a drop down list in a rehosted designer environment. My problem is I want to get variable's name along with its value.
Let's say my custom activity has "InArgument MyVar{ get; set; }".
I'm currently getting the variable's name by parsing "((Microsoft.VisualBasic.Activities.VisualBasicValue)MyVar.Expression).ExpressionText". Is there any better way?
You can't surelly know the true value of an argument until the runtime.
But, you can take it's default value, using those extension methods:
public static T GetImediateValueOrDefault<T>(Activity<T> activity, ModelItem modelItem)
{
if (activity == null)
return default(T);
var exprAsLiteral = activity as Literal<T>;
if (exprAsLiteral != null)
return exprAsLiteral.Value;
var exprAsVbValue = activity as Microsoft.VisualBasic.Activities.VisualBasicValue<string>;
if (exprAsVbValue != null)
return modelItem.GetDefaultValueOfScopedVariable<T>(exprAsVbValue.ExpressionText);
return default(T);
}
public static T GetDefaultValueOfScopedVariable<T>(this ModelItem modelItem, string variableName)
{
IEnumerable<ModelItem> scopedVariables = modelItem.GetScopedVariables();
ModelItem variableModelItem = scopedVariables.FirstOrDefault(v => Equals(variableName, v.Properties["Name"].ComputedValue));
if (variableModelItem == null)
throw new KeyNotFoundException();
Variable<T> variable = variableModelItem.GetCurrentValue() as Variable<T>;
if (variable == null)
return default(T);
return GetImediateValueOrDefault(variable.Default, modelItem);
}
Not guaranteed, use with caution

Picking out Just JSON Data Returned from ASP.NET MVC3 controller Update

I've got data returned from my JavaScript client that just includes the data that has changed. That is, I may have an array with each row containing 10 columns of JSON downloaded, but on the Update, only the data that is returned to me is the data that got updated. On my update, I only want to update those columns that are changed (not all of them).
In other words, I have code like below but because I'm passing in an instance of the "President" class, I have no way of knowing what actually came in on the original JSON.
How can I just update what comes into my MVC3 update method and not all columns. That is, 8 of the columns may not come in and will be null in the "data" parameter passed in. I don't want to wipe out all my data because of that.
[HttpPost]
public JsonResult Update(President data)
{
bool success = false;
string message = "no record found";
if (data != null && data.Id > 0)
{
using (var db = new USPresidentsDb())
{
var rec = db.Presidents.FirstOrDefault(a => a.Id == data.Id);
rec.FirstName = data.FirstName;
db.SaveChanges();
success = true;
message = "Update method called successfully";
}
}
return Json(new
{
data,
success,
message
});
}
rec.FirstName = data.FirstName ?? rec.FirstName;
I would use reflection in this case because the code will be too messy like
if (data.FirstName != null)
rec.FirstName = data.FirstName
.
.
.
and so on for all the fields
Using reflection, it would be easier to do this. See this method
public static void CopyOnlyModifiedData<T>(T source, ref T destination)
{
foreach (var propertyInfo in source.GetType().GetProperties())
{
object value = propertyInfo.GetValue(source, null);
if (value!= null && !value.GetType().IsValueType)
{
destination.GetType().GetProperty(propertyInfo.Name, value.GetType()).SetValue(destination, value, null);
}
}
}
USAGE
CopyOnlyModifiedData<President>(data, ref rec);
Please mind that, this won't work for value type properties.

The best way to build Dynamic LINQ query

Hi I am looking for best method for writing Dynamic LINQ query.
I have a function like
public IQueryable<Student> FindByAllStudents(int? id, string Name, int? CourseID, bool? IsActive) // like this way, all field values are passed
{
// code for compairision
return db.Student;
}
we can also write db.Students.where(predicate)
or
a query like
var students = from s in db.students where s.Name.Contains(Name)
s.ID.Equals(id)
//and so on....
So will this method works if i don't pass ID (i.e. Null)?
is proper way for all the datatypes?
The point is function can have all null values as a parameter for equivalence of select * from statement.
can any one help me to build best query with sample code?
Okay, it's not entirely clear what you want, but if you're trying to only add where clauses for the parameters which are non-null, you could do:
public IQueryable<Student> FindByAllStudents
(int? id, string name, int? courseID, bool? isActive)
{
IQueryable<Student> query = db.Student;
if (id != null)
{
query = query.Where(student => student.ID == id.Value);
}
if (name != null)
{
query = query.Where(student => student.Name.Contains(name));
}
if (courseID != null)
{
query = query.Where(student => student.CourseID == courseID.Value);
}
if (isActive != null)
{
query = query.Where(student => student.IsActive == isActive.Value);
}
return query;
}
I haven't tried that, and it's possible that LINQ to SQL would get confused by the code to find the value of the nullable value types. You may need to write code like this:
if (courseID != null)
{
int queryCourseID = courseID.Value;
query = query.Where(student => student.CourseID == queryCourseID);
}
It's worth trying the simpler form first though :)
Of course, all this gets a bit irritating. A helpful extension method could make life more concise:
public static IQueryable<TSource> OptionalWhere<TSource, TParameter>
(IQueryable<TSource> source,
TParameter? parameter,
Func<TParameter, Expression<Func<TSource,bool>>> whereClause)
where TParameter : struct
{
IQueryable<TSource> ret = source;
if (parameter != null)
{
ret = ret.Where(whereClause(parameter.Value));
}
return ret;
}
You'd then use it like this:
public IQueryable<Student> FindByAllStudents
(int? id, string name, int? courseID, bool? isActive)
{
IQueryable<Student> query = db.Student
.OptionalWhere(id, x => (student => student.ID == x))
.OptionalWhere(courseID, x => (student => student.CourseID == x))
.OptionalWhere(isActive, x => (student => student.IsActive == x));
if (name != null)
{
query = query.Where(student => student.Name.Contains(name));
}
return query;
}
Using a higher order function like this could get confusing if you're not really comfortable with it though, so if you're not doing very many queries like this you might want to stick with the longer but simpler code.

Resources