This is the specific line of code that I need to mock.
IGenericRepository<Foo> _fooRepository;
var listOfIds = await _fooRepository.GetAllAsync(o => o.Ids);
This is getting a list of int to represent the IDs in this data table. In other words,
select Ids from Table
FooRepository is implemented with IGenericRepository all using Entity Frameworks. The Ids field in the underlying table is just integer values and I'm trying to get a list of int out of it. I don't want any other columns.
So I have tried the following to no avail:
1.
_listOfIds = new List<int> {1,2,3,4,5};
_fooRepositoryMock.Setup(o => o.GetAllAsync(
It.IsAny<Expression<Func<Foo, bool>>>()))
.Returns((Expression<Func<Foo, bool>> Predicate) =>
Task.FromResult(_listOfids.Where(Predicate.Compile()).ToList()
as ICollection<int>));
With this, IntelliSense complains that it cannot convert from...
'System.Func<Foo, Bool> to System.Func<int, int, bool>"
I tried at first messing around with the different types going in and out of the Func delegate. But I'm still stuck with the same error.
2.
I tried to then just use a default as I don't particularly mind if it tests this line completely. The list of IDs is just used later on in the method. But I need to mock it because if it's null, it's causing a test further down the test method to fail.
_listOfids= new List<int> {1,2,3,4,5};
_fooRepositoryMock.SetReturnsDefault(_listOfIds);
For some reason, when debugging the listOfIds remains null.
I'm kinda stuck on this one. The only thing that I can think of is to just stick this line of code into a helper method and mock the helper instead. But it just seems a really shoddy way to rewrite the code just to make a test pass.
You don't have to specify the parameters for Returns method call. Also Moq includes another method for setting results of async methods.
_fooRepositoryMock.Setup(o => o.GetAllAsync(It.IsAny<Expression<Func<Foo, int>>>()))
.ReturnsAsync(idList);
Related
LINQ newbie here.
I have a long LINQ query, called it MYLONGQUERY, that returns a collection of certain class instances. If the list is not empty, I want to return a property (MYPROPERTY) of the first instance; otherwise it returns some default value (DEFAULTPROPERTY). So the query looks like this
(0 != MYLONGQUERY.count()) ? MYLONGQUERY.FirstOrDefault().MYPROPERTY: DEFAULTPROPERTY
This works fine. However, I don't like the fact that I have to repeat MYLONGQUERY before and after "?". I have been trying Let and Into, but have not been able to get those to work. And it has to be Method Syntax, not Query Syntax. Suggestions? Appreciate it.
You have to select the property first, then you can specify the default-value with DefaultIfEmpty:
var prop = MYLONGQUERY
.Select(x => x.MYPROPERTY)
.DefaultIfEmpty(DEFAULTPROPERTY) // new default-value
.First(); // never exception
There is a table, it is a poco entity generated by entity framework.
class Log
{
int DoneByEmpId;
string DoneByEmpName
}
I am retrieving a list from the data base. I want distinct values based on donebyempid and order by those values empname.
I have tried lot of ways to do it but it is not working
var lstLogUsers = (context.Logs.GroupBy(logList => logList.DoneByEmpId).Select(item => item.First())).ToList(); // it gives error
this one get all the user.
var lstLogUsers = context.Logs.ToList().OrderBy(logList => logList.DoneByEmpName).Distinct();
Can any one suggest how to achieve this.
Can I just point out that you probably have a problem with your data model here? I would imagine you should just have DoneByEmpId here, and a separate table Employee which has EmpId and Name.
I think this is why you are needing to use Distinct/GroupBy (which doesn't really work for this scenario, as you are finding).
I'm not near a compiler, so i can't test it, but...
Use the other version of Distinct(), the one that takes an IEqualityComparer<TSource> argument, and then use OrderBy().
See here for example.
I'm working on a custom linq extension for nHibernate by extending the BaseHqlGeneratorForMethod. The technique is documented here:
http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html
I've had success with implementing these for various types of operations, but I must say - converting a simple linq expression to its full expression tree is not easy! I'm stuck on one now.
For this example, I have three entities. Employee, Group, and EmployeeGroup. The EmployeeGroup class sets up a many-to-many relationship between Employee and Group. I must specifically create the intermediate class because there are additional properties to track like specific permissions each employee has in each group. So there are two one-to-many relationships, rather than an nHibernate many-to-many relationship.
Now say I want to get all groups that contain a specific employee. I can write this query:
var groups = session.Query<Group>()
.Where(g => g.EmployeeGroups.Any(eg => eg.Employee == employee));
This works fine, but it's a lot to type. I'd much rather be able to do this:
var groups = session.Query<Group>().Where(g => g.HasEmployee(employee));
I start by creating an extension method like so:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This works when querying a local list of groups, but not against the nHibernate session. For that, I have to also create a linq extension and register it. Just like in the article (linked above), I create a GroupHasEmployeeGenerator class that extends BaseHqlGeneratorForMethod. I set its .SupportedMethods property to reference my HasEmployee extension method.
Where I get lost is in the override to BuildHql. The expression to build gets complicated pretty fast. I figure since I'm replacing the .Any clause - a good place to start is with the source for the built-in AnyHqlGenerator class. But that doesn't take into account that the source is a property of the original element, and it also doesn't take into account that I don't have a lambda expression to represent the where clause. I need to build these parts manually.
There's no point in posting my attempts so far, as they've all be quite far from anything that would work.
Will someone please help me convert this simple expression into the approprate set of methods for the BuildHql method override?
If there is any better documentation out there for this, please let me know. Thanks.
I know this question is a year old, but I ran into a very similar issue when implementing BaseHqlGeneratorForMethod today.
The input to BuildHql contains a collection of System.Linq.Expressions.Expression arguments that are passed to your extension method. Using these arguments, you can build an expression tree that represents the implementation of your extension method. If the resulting expression is something NHibernate.Linq supports, then you can transform that expression to a subtree of Hql using the provided IHqlExpressionVisitor.
In your example:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This would become something similar to this:
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
var AnyMethod = EnumerableHelper.GetMethod("Any", new[] {typeof(IEnumerable<EmployeeGroup>), typeof(Func<EmployeeGroup, bool>)}, new[] {typeof(EmployeeGroup)});
var EmployeeGroupsProperty = ReflectionHelper.GetProperty<Group>(g => g.EmployeeGroups);
var EmployeeProperty = ReflectionHelper.GetProperty<EmployeeGroup>(eg => eg.Employee);
var EmployeeGroupParameter = Expression.Parameter(typeof(EmployeeGroup));
var EmployeeGroupPredicate = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(EmployeeGroupParameter, EmployeeProperty), arguments[1]), EmployeeGroupParameter);
var CallExpression = Expression.Call(AnyMethod, Expression.MakeMemberAccess(arguments[0], EmployeeGroupsProperty), EmployeeGroupPredicate);
return visitor.Visit(CallExpression);
}
I can't really test this specific example, but the same approach worked for me when providing support for my own extension method.
I have a method to build an expression for a linq query for a given type, property, and value. This works wonderfully as long as the property on the type is NOT nullable. Here is the example I am working from (http://www.marcuswhitworth.com/2009/12/dynamic-linq-with-expression-trees) I am calling the Equals method on the property. However I have discovered that the Equals method for Nullable types takes an Object as a parameter instead of the Nullable type. I attempted to use GetValueOrDefault to hide the null values but EF doesn't support that method. As a simple example the following code will throw an error:
decimal? testVal = new decimal?(2100);
var test = (from i in context.Leases where i.AnnualRental.Equals(testVal) select i).ToList();
However if you use == instead of the Equals() method it will work OK. I am not sure how to convert the code to use == instead of Equals() however. Any suggestions will be greatly appreciated.
If you say ==, you generate a BinaryExpression with NodeType as ExpressionType.Equal. http://msdn.microsoft.com/en-us/library/bb361179.aspx
If you say .Equals(x), you generate a MethodCallExpression. The MethodCallExpressions that LinqToEntities may translate into Sql is a limitted list (for example none of your own undecorated methods are in that list). Nullable<T>.Equals(x) is apparently not on that list.
Don't say .Equals(x) to LinqToEntities.
Why do I get the error:
Unable to create a constant value of type 'Closure type'. Only
primitive types (for instance Int32, String and Guid) are supported in
this context.
When I try to enumerate the following Linq query?
IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
var myList = from person in entities.vSearchPeople
where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}
Update:
If I try the following just to try to isolate the problem, I get the same error:
where upperSearchList.All(arg => arg == arg)
So it looks like the problem is with the All method, right? Any suggestions?
It looks like you're trying to do the equivalent of a "WHERE...IN" condition. Check out How to write 'WHERE IN' style queries using LINQ to Entities for an example of how to do that type of query with LINQ to Entities.
Also, I think the error message is particularly unhelpful in this case because .Contains is not followed by parentheses, which causes the compiler to recognize the whole predicate as a lambda expression.
I've spent the last 6 months battling this limitation with EF 3.5 and while I'm not the smartest person in the world, I'm pretty sure I have something useful to offer on this topic.
The SQL generated by growing a 50 mile high tree of "OR style" expressions will result in a poor query execution plan. I'm dealing with a few million rows and the impact is substantial.
There is a little hack I found to do a SQL 'in' that helps if you are just looking for a bunch of entities by id:
private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}
where pkIDColumn is your primary key id column name of your Entity1 table.
BUT KEEP READING!
This is fine, but it requires that I already have the ids of what I need to find. Sometimes I just want my expressions to reach into other relations and what I do have is criteria for those connected relations.
If I had more time I would try to represent this visually, but I don't so just study this sentence a moment: Consider a schema with a Person, GovernmentId, and GovernmentIdType tables. Andrew Tappert (Person) has two id cards (GovernmentId), one from Oregon (GovernmentIdType) and one from Washington (GovernmentIdType).
Now generate an edmx from it.
Now imagine you want to find all the people having a certain ID value, say 1234567.
This can be accomplished with a single database hit with this:
dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));
IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);
Do you see the subquery here? The generated sql will use 'joins' instead of sub-queries, but the effect is the same. These days SQL server optimizes subqueries into joins under the covers anyway, but anyway...
The key to this working is the .Any inside the expression.
I have found the cause of the error (I am using Framework 4.5). The problem is, that EF a complex type, that is passed in the "Contains"-parameter, can not translate into an SQL query. EF can use in a SQL query only simple types such as int, string...
this.GetAll().Where(p => !assignedFunctions.Contains(p))
GetAll provides a list of objects with a complex type (for example: "Function"). So therefore, I would try here to receive an instance of this complex type in my SQL query, which naturally can not work!
If I can extract from my list, parameters which are suited to my search, I can use:
var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))
Now EF no longer has the complex type "Function" to work, but eg with a simple type (long). And that works fine!
I got this error message when my array object used in the .All function is null
After I initialized the array object, (upperSearchList in your case), the error is gone
The error message was misleading in this case
where upperSearchList.All(arg => person.someproperty.StartsWith(arg)))