I’m attempting to add a property in a partial class to an entity framework model that includes entities that have been mapped via navigation properties unioned with some additional rows.
Database:
I have a Users table with a UserID primary key. Additionally, I have a Tags table with a OwnerUserID (foreign key, nullable), which is set to the UserID if it is user specific, but may also be null to indicate it applies to all users.
EF Model:
The navigation property Users.Tags is properly generated to include all tags that are explicitly assigned to that user.
Problem:
I need a property on the User entity that includes all tags that have the OwnerUserID of the User and those that are null.
So I want to be able to say something like:
public partial class User
{
public IEnumerable<Tag> VisibleTags
{
get
{
return tags = (from t in {AllTags}
where t.PrivateUserID == null
select t).Union(
from t in this.Tags
select t);
}
}
}
…where {AllTags} represents all tags in the system.
A quick comment on the design:
I am not a big fan of nullable values in a database, especially when the
nullprovides contextual information, like the value applying to all users, as opposed to no users.You might want to consider a design where you can group users, and tags would be visible to a group of users. This would be more flexible in case your needs changed in the future, and more explicit. It also would make it so you can make the column non-nullable.
If you don’t want to build that into your system now, I’d personally plot out what a migration from your current design to a group-based design would look like, just to make sure you didn’t paint yourself into a corner design-wise.
The problem at hand
You get
AllTagsfrom the context, so you’re going to have to use a context object.Attempt 1
One way to do this would be to create a method on the context that accepts either a
Useror aUserId.I don’t completely like because I don’t think a context should be used to make queries. That is a job for the “repository” (entity/
DbSet/DataSetclass).Attempt 2
Another way (which would make it accessible off the user) would be to add a context parameter to your getter method:
I like this even less than the first because a “repository” (entity/
DataSet/DbSet) shouldn’t be allowed to know anything about a context.Attempt 3
You could create a query wrapper object to solve this. I generally suggest you write complex queries this way when you can, so they are reusable.
The trick is figuring out a good domain specific name name for the class…