views:

205

answers:

2

I have a domain entity that has a flagged enum as a property. The flagged enum is the target audience for the these entities. The user then has a flagged enum value of the entities they should see. I am trying to figure out the correct expression to select entities that meet the target audience for the user.

public class File
{
    public virtual TargetAudience TargetAudience { get; set; }
}

[Flags]
public enum TargetAudience
{
    Audience1 = 1,
    Audience2 = 2,
    Audience3 = 4,
    Audience4 = 8
}

Expression: (This works when performed on a IList<File>, but doesn't work on a query to the database.)

public Expression<Func<File, bool>> Expression
{
     get { return ((x.TargetAudience & UserTargetedAudience) > 0); }
}

Any suggestions would be helpful.

+1  A: 

In what way does it not work in a query to the database?

You aren't showing your full implementation nor your mapping. Are you persisting TargetAudience as a numeric datatype?

Unless you are jumping through some hoops to do so, your enum will be stored as text in the database, so you can't perform bitwise operations on it. (This behaviour is contrary to some of what I've seen around blogs, etc., so I don't know (a) if it has changed since prior versions, (b) if it is somehow unique to the SQLite provider that I'm using, or (c) if it is mapped this way by Fluent NHibernate.)

You can perform a textual comparison. Combined flags get stored as a comma-separated list, so TargetAudience.Audience4 | TargetAudience.Audience1 would be persisted not as 9, but as Audience1, Audience4. Note that it gets persisted in ascending order, even though I specified them in reverse order.

var query = session.Linq<File>()
    .Where(f => f.TargetAudience.ToString() == "Audience1, Audience4");

You could write a few [extension] methods in short order that would encapsulate the nastiness of doing these textual comparisons.

edit:

See http://stackoverflow.com/questions/439003/how-do-you-map-an-enum-as-an-int-value-with-fluent-nhibernate for information about persisting enums as integers

Jay
A: 

You can map an enum property as an int column, with method CustomType.

public class FileMap : ClassMap<File>
{
    Map( x => x.TargetAudience ).CustomType<int>();
}

// or the equivalent for automap
.Override<File>(map => {  
    map.Map( x => x.TargetAudience ).CustomType<int>();
});
Lachlan Roche