EntityFramework string Include() a child property - entity-framework

I had an Include method like so
public static IQueryable<SlideSet> IncludeParameters(this IDbSet<SlideSet> storage) {
return storage.Include(ss => ss.Params.Select(x => x.Parameter));
}
I am cleaning up my domain model and it no longer makes sense to have SlideSet.Params be public.
I know that there is a form of IDbSet<>.Include() that takes a string parameter. What is the syntax for using a string while descending into the child property like this?
btw, for those who are wondering, I'm pretty sure
return storage.Include(ss => ss.Params.Select(x => x.Parameter));
is identical to
return storage.Include(ss => ss.Params.Include(x => x.Parameter));

Just use .:
return storage.Include("Params.Parameter");

Related

Why can't I create a callback for the List Find method in Moq?

I created an extension method that lets me treat a List as DbSet for testing purposes (actually, I found this idea in another question here on stack overflow, and it's been fairly useful). Coded as follows:
public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var mockDbSet = new Mock<DbSet<T>>();
mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
mockDbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>(sourceList.Add);
mockDbSet.Setup(d => d.Find(It.IsAny<object[]>())).Callback(sourceList.Find);
return mockDbSet.Object;
}
I had been using Add for awhile, and that works perfectly. However, when I try to add the callback for Find, I get a compiler error saying that it can't convert a method group to an action. Why is sourceList.Add an Action, but sourceList.Find is a method group?
I'll admit I'm not particularly familiar with C# delegates, so it's likely I'm missing something very obvious. Thanks in advance.
The reason Add works is because the List<T>.Add method group contains a single method which takes a single argument of type T and returns void. This method has the same signature as an Action<T> which is one of the overloads of the Callback method (the one with a single generic type parameter, Callback<T>), therefore the List<T>.Add method group can be converted to an Action<T>.
With Find, you are trying to call the Callback method (as opposed to Callback<T>) which expects an Action parameter (as opposed to Action<T>). The difference here is that an Action does not take any parameters, but an Action<T> takes a single parameter of type T. The List<T>.Find method group cannot be converted to an Action because all the Find methods (there is only one anyway) take input parameters.
The following will compile:
public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
{
var mockDbSet = new Mock<DbSet<T>>();
mockDbSet.Setup(d => d.Find(It.IsAny<object[]>())).Callback<Predicate<T>>(t => sourceList.Find(t));
return mockDbSet.Object;
}
Note that I have called .Callback<Predicate<T>> because the List<T>.Find method expects and argument of type Predicate. Also note I have had to write t => sourceList.Find(t) instead of sourceList.Find because Find returns a value (which means it doesn't match the signature of Action<Predicate<T>>). By writing it as a lambda expression the return value will be thrown away.
Note that although this compiles it will not actually work because the DbSet.Find method actually takes an object[] for it's parameter, not a Predicate<T>, so you will likely have to do something like this:
public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
{
var mockDbSet = new Mock<DbSet<T>>();
mockDbSet.Setup(d => d.Find(It.IsAny<object[]>())).Callback<object[]>(keyValues => sourceList.Find(keyValues.Contains));
return mockDbSet.Object;
}
This last point has more to do with how to use the Moq library that how to use method groups, delegates and lambdas - there is all sorts of syntactic sugar going on with this line which is hiding what is actually relevant to the compiler and what isn't.

Symfony 2 : Get available choices of a choice Field Type

1) Is there a symfony method ?
I've got a basic form (not mapped to the database), with some choice fields, for example :
$builder->add('civility', 'choice', array('choices'=> array('m' => 'M.', 'mme' => 'Mme', 'mlle' => 'Mlle')))
How can I - after the form was submited - in the action (or, even better, in the template), retrieve the label value of the option instead of the form submitted value ? (in this case, I want to be able to render "M." in the template instead of "m")
I was thinking about something like $form->get("civility")->getChoiceLabel($form->get("civility")->getData())
But I didn't find anything like this in the documentation (though there was something like that in Symfony1).
2) If Really not, what's the best way to make it ?
Thus, I was thinking about creating some methods to do that, in the Data Class used by the form, like .. :
private $choices = array("civility" => array('m' => 'M.', 'mme' => 'Mme', 'mlle' => 'Mlle'));
static public function getChoiceLabel($choice_value, $field_name)
{
return self::$choices[$field_name][$choice_value];
}
static public function getChoices($field_name)
{
return self::$choices[$field_name];
}
But the problem is that we're not supposed to use static methods in the twig template (I have to make it Static to be able to use it in the form generation, the buildForm method, and not duplicate some code).
You can access choses labels and their values like this:
$form->get('civility')->getConfig()->getOption('choices');
Read more: Symfony\Component\Form\FormConfigInterface::getOption()

Using Expression Trees as an argument constraint

Can I use an Expression Tree as an argument constraint in a FakeIteasy CallTo assertion?
Given a method on an interface with the following signature:
interface IRepository<TEntity>
{
TEntity Single(Expression<Func<TEntity, bool>> predicate);
Being called in code like so:
Flight flight = repository.Single(f => f.ID == id);
I have in mind a unit test doing something like this:
Expression<Func<Flight, bool>> myExpression = flight => flight.ID == 1;
A.CallTo(() => repository.Single(
A<Expression<Func<Flight, bool>>>.That.Matches(myExpression)))
.Returns(new Flight());
However this produces a warning: Try specifying type arguments explicitly.
I am currently having to use the Ignored property which is not ideal.
The "Matches"-method takes a lambda but you're trying to pass it the expression. What are you trying to say with the "Matches"-call? Are you matching on equality? In that case you'd just write:
A.CallTo(() => repository.Single(myExpression)).Returns(new Flight());
If you want to constrain the expression on something else you'd have to pass a predicate of the type: Func<Expression<Func<Flight, bool>>, bool> to the "Matches"-method.
Thanks Patrik,
Examining the expression was exactly what I needed to do, i.e. parse the expression (f => f.ID == id) and execute the Right side of the == to get its runtime value.
In code this looks like this:
A.CallTo(() => flightRepository.Single(A<Expression<Func<Flight, bool>>>.That
.Matches(exp => Expression.Lambda<Func<int>>(((BinaryExpression)exp.Body).Right).Compile().Invoke() == 1)))
.Returns(new Flight());
However I can't help thinking that there must be a more elegant way to achieve the same end. I'll leave that for another day though.
Thanks again,
Michael McDowell
I had the same problem while attempting to assert an expression as an argument but I was using Moq. The solution should work for you though as well...
I give most of the credit to this answer to a similar question:
Moq Expect On IRepository Passing Expression
It basically says you can do a ToString() on the expressions and compare them. It is kind of hacky but it only has one downside; the variables names in the lambda expression must match.
Here is an example...
[Test]
public void TestWhichComparesExpressions()
{
// setup
_mockRepository.Setup(x => x.GetByFilter(MatchQuery())).Returns(new List<Record>());
// execute
var records = _service.GetRecordsByFilter();
// assert
Assert.IsNotNull(records);
Assert.AreEqual(0, records.Count());
}
private static Expression<Func<DomainRecord, bool>> MatchQuery()
{
return MatchExpression(ServiceClass.QueryForTheRecords); // constant
}
// https://stackoverflow.com/questions/288413/moq-expect-on-irepository-passing-expression/1120836#1120836
private static Expression<Func<DomainRecord, bool>> MatchExpression(Expression<Func<DomainRecord, bool>> expression)
{
return It.Is<Expression<Func<DomainRecord, bool>>>(e => e.ToString() == expression.ToString());
}
I decided to put the expression into a constant on the class which used it which guaranteed it would be the same in the test if someone changed the lambda expressions's variable names.

How do I mock a Where clause in EF4

I am re-writing this question to make it clearer what I need to do. I am trying to use Rhino-Mock to test:
public IQueryable<TxRxMode> GetAllModes()
{
return m_context.TxRxModes.Where(txRxMode => txRxMode.Active);
}
Here's the code:
var context = MockRepository.GenerateStub<IProjectContext>();
//Returns an empty list
context.Expect(c => c.TxRxModes.Where(Arg<Func<TxRxMode, bool>>.Is.Anything)).Return(new List<TxRxMode>().AsQueryable());
TxRxModes in an IObjectSet property on the context and I want it to return an empty IQueryable<TxRxMode> object when the return m_context.TxRxModes.Where(txRxMode => txRxMode.Active); code is called.
When I run this, the Expect method call throws the an ArgumentNullException:
Value cannot be null.
Parameter name: predicate
I have tried the simpler:
IObjectSet<TxRxMode> modes = MockRepository.GenerateStub<IObjectSet<TxRxMode>>();
context.Expect(c => c.TxRxModes).Return(modes);
but this throws a null reference exception when I call
return m_context.TxRxModes.Where(txRxMode => txRxMode.Active);
Basically, this is part of the method I am trying to mock, so the key question is how do I mock this Where statement?
Where is actually a global static method and you shouldn't be mocking it. It operates on an IEnumerable however and you could just mock that.
Its kind of a hassle doing it with rhino mocks however. I would recommend doing the mock manually (if you need to do it at all).

Eager Loading aggregate roots with Entity Framework

I would like to create a more structured approach to loading the needed entity-tree:
I need a serious amount of data, so I'm doing this using type-safe Includes (just a normal Include but with Lambda's) as shown here.
As I said, I need a lot of data, basically a whole entity tree under 1 parent item.
Now, I could do this doing something like:
context.House
.Include(x => x.Doors)
.Include(x => x.Doors.FirstOrDefault().Joint)
.Include(x => x.Doors.FirstOrDefault().Joint.FirstOrDefault().JointCategory)
.Include(x => x.Doors.FirstOrDefault().Joint.FirstOrDefault().JointCategory.JointType)
.Include(x => x.Windows)
// ... same thing
.Include(x => x.Roof)
// ... same thing
As you can see, this line filled with includes can get quite huge. This is in fact a very simplified sample of the actual code (which doesn't include houses btw)
So what I would like to do is creating methods, responsible for its branch in the tree. Where the method can accept the object query and include the child, and in its turn, call the "child-loader methods". Also, the parent shouldn't matter, as long as it has a property with the type of the child.
This probably does not make much sense so:
public void LoadHouse(int id)
{
// ...
ObjectQuery<House> query = context.House;
// and now?
LoadDoors(query, x => x.Door);
}
public void LoadDoors<T>(ObjectQuery<T> query, ..?..)
{
// ... ?
LoadJoints(...)
}
And so on. But I can't really get my head around it... There's a missing link between the incoming query and calling the child methods.
Has anyone done something like this? Or could anyone give me some pointers?
Try something like this instead:
query = LoadDoors(query, x => x.Door);
Where LoadX returns the result of calling Include.