Come faccio a specificare una maschera di bit / bitfield clausola WHERE utilizzando di NHibernate Criterion API [duplicato]

StackOverflow https://stackoverflow.com/questions/9304692

Domanda

Eventuali duplicati:
Come bandiere di query memorizzata come enum in NHibernate

ho tre tavoli - Recipient, Message, MessageType

sguardi MessageType come questo:

| ID | Description  |
|====|==============|
|  1 | JobAlert     |
|  2 | Newsletter   |
|  3 | SpecialOffer |
|  4 | Survey       |

Recipient contiene una colonna integer che viene utilizzato come un campo di bit; i destinatari possono scegliere quali tipi di messaggio che vogliono ricevere; Se il destinatario desidera ricevere le newsletter e le offerte speciali, imposteremo il loro campo di bit per (2 ^ 2) | (2 ^ 3)

Message contiene un riferimento a MessageTypeId e computerizzata MessageTypeBitFlag colonna che è definito come POWER(2, MessageTypeId)

La mia domanda espressa in SQL sembra qualcosa di simile:

SELECT * FROM Message, Recipient
  WHERE Recipient.MessageTypeBitField & Message.MessageTypeBitFlag > 0

facendo un bit-E sul campo di bit e le colonne bitflag, è facile selezionare solo i messaggi che un determinato destinatario è interessato a.

Il problema è che non sto facendo questo in SQL -. Ho bisogno di aggiungere questo come un'opzione aggiuntiva per un abbastanza ricco sistema costruito sul Criteri API NHibernate

C'è un modo per esprimere questo criterio tramite l'API NHibernate -? O utilizzando l'API o con l'aggiunta di una clausola SQL / HQL ai criteri esistenti

È stato utile?

Soluzione

OK, ecco una specifica implementazione basata su questo post legati presentata da Firo , perché ho dovuto adattare questo un po 'per farlo funzionare:

/// <summary>An NHibernate criterion that does bitwise comparison to match a bit flag against a bitmask.</summary>
public class BitMask : LogicalExpression {
    private BitMask(string propertyName, object value, string op) :
        base(new SimpleExpression(propertyName, value, op), Expression.Sql("?", 0, NHibernateUtil.Int64)) {
    }

    protected override string Op {
        get { return ">"; }
    }
    /// <summary>Create a bitwise filter criterion - i.e. one that will be satisified if <code><paramref name="propertyName"/> &amp; <paramref name="bits"/> &gt; 0</code></summary>
    public static BitMask Matches(string propertyName, long bits) {
        return new BitMask(propertyName, bits, " & ");
    }
}

e quindi utilizzare tramite l'API Criteri come segue:

public IEnumerable<Message> GetMessagesForRecipient(Recipient r) {
    var messages = session.CreateCriteria<Message>()
        .Add(BitMask.Matches("MessageTypeBitFlag ", r.MessageTypeBitField))
        .List<Message>();
    return(messages);
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top