Note that there are some explanatory texts on larger screens.

plurals
  1. POEntity Framework - expression on similar properties
    text
    copied!<p>I'm still fairly new to Entity Framework (currently developing using v4.1), so I may be going about this in completely the wrong way, so I'd welcome any guidance. </p> <p>I currently have two classes: <strong>Item</strong> which just has a few simple fields, and <strong>FavouriteItem</strong> which holds a reference to an item and a user (but the user relationship isn't relevant to the discussion). The item has a nullable <strong>DateVisible</strong> field which I'm using as a flag to indicate if an item should be displayed or not.</p> <p>In order to get a list of visible items, I'm using a simple query:</p> <pre><code>var items = itemRepository .QueryAll() .Where(i =&gt; i.DateVisible &lt;= DateTime.Now) </code></pre> <p>Where obviously QueryAll returns an IQueryable. This is a straightforward example, as the conditions are a little more complex, but it demonstrates my issue.</p> <p>Next, if I want to return a list of favourites for items which are visible, then I can do a similar query:</p> <pre><code>var favourites= favouriteRepository .QueryAll() .Where(f =&gt; f.Item.DateVisible &lt;= DateTime.Now) </code></pre> <p>This works fine. However, the code is duplicated. So what I'd like to do is somehow make this code more central - as I'm about to add a <strong>FollowingItem</strong> class which again has an Item property, and so I'd have to repeat the code again - not good.</p> <p>I started to create an expression for the list of items, which works well:</p> <pre><code>public static Expression&lt;Func&lt;Item, bool&gt;&gt; IsVisibleExpression&lt;Item&gt;() { return item =&gt; item.DateVisible != null &amp;&amp; item.DateVisible &lt;= DateTime.Now; } public static IQueryable&lt;Item&gt; WhereVisible&lt;Item&gt;(this IQueryable&lt;Item&gt; queryable) { return queryable.Where(Item.IsVisibleExpression()); } var items = itemRepository .QueryAll() .WhereVisible() </code></pre> <p>And again, I can create these expressions for each class:</p> <pre><code>public static Expression&lt;Func&lt;FavouriteItem, bool&gt;&gt; IsVisibleExpression&lt;FavouriteItem&gt;() { return favourite =&gt; favourite.Item.DateVisible != null &amp;&amp; favourite.Item.DateVisible &lt;= DateTime.Now; } </code></pre> <p>But this again just duplicates the code. Is there any way the same code be used between them. I know I could do a join on the <code>itemRepository.QueryAll().WhereVisible()</code>, but is there not a way to do this that doesn't involve doing this everywhere?</p> <p><strong>Update</strong>: I tried creating an interface for the classes:</p> <pre><code>public interface IEntityWithItem { Item Item { get; set; } } </code></pre> <p>And creating an expression for it:</p> <pre><code> public static IQueryable&lt;TEntity&gt; WhereItemVisible&lt;TEntity&gt;(this IQueryable&lt;TEntity&gt; queryable) where TEntity : IEntityWithItem { return queryable.Where(ui =&gt; ui.Item.DateVisibleFrom != null &amp;&amp; ui.Item.DateVisibleFrom.Value &lt;= DateTime.Now); } </code></pre> <p>Which I've called from:</p> <pre><code>// Get the favourites var favourites = favouriteItemRepository.QueryAll() .WhereItemVisible() .Where(favourite =&gt; favourite.UserId == user.Id); </code></pre> <p>But it gives the error: "<em>Unable to cast the type 'FavouriteItem' to type 'IEntityWithItem'. LINQ to Entities only supports casting Entity Data Model primitive types.</em>"</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload