2010-04-13 9 views
0

J'insère un enregistrement dans ma table, mais je veux être en mesure de définir mon champ SortOrder sur insert à SELECT MAX (SortOrder) + 1 FROM Catégorie O Site SiteID = @SiteID. Quelle est la manière la plus simple de le faire?Comment effectuer une requête de temps d'exécution en utilisant Linq à NHibernate

Voici ma structure de données:
Catégorie
ID
SITEID
SortOrder
Nom

J'utilise Fluent NHibernate et LINQ to NHibernate. Merci pour toute aide!

+1

ce qui est la base de données? dans SQL, vous pouvez simplement faire de la colonne une colonne d'auto-incrémentation, et ce que vous décrivez se produit par défaut. D'autres serveurs de base de données font des choses similaires. Il n'y a pas de code requis pour y arriver. Lors de l'insertion, vous ne fournissez pas de valeur pour SortOrder. – Cheeso

+0

Il s'agit de SQL Server, mais il existe des sous-ensembles dans la table, ce qui explique pourquoi j'ai filtré par SiteID. –

Répondre

1

Ok, voici 2 façons. Le plus simple ne peut impliquer NHibernate puisque vous utilisez SQL Server ... Vous pouvez tout simplement créer un déclencheur INSTEAD OF INSERT sur la table, comme ceci:

CREATE TRIGGER tgINSCategory ON Category INSTEAD OF INSERT 
AS 
BEGIN 
    SET NOCOUNT ON 

    INSERT INTO Category (SiteID, Name, SortOrder) 
    SELECT SiteID, Name, 
     ISNULL((SELECT MAX(c.SortOrder) 
       FROM Category c INNER JOIN INSERTED i ON c.SiteID = i.SiteID), 0) + 1 
    FROM INSERTED 
END 

Dans ce premier scénario vous simplement NHibernate carte du SortOrder colonne en lecture seule (il suffit d'ajouter .ReadOnly() sur la propriété SortOrder de la classe nhibernate courante).

La seconde méthode consisterait à utiliser la fonction intégrée de NHibernate appelée intercepteurs. Avec un intercepteur, vous pouvez exécuter le code que vous voulez juste au moment où NHibernate génère normalement du SQL pour exécuter une action DML. Les informations de création ci-dessous auto-inserts, mais serait très similaire à ce que vous auriez besoin. IInsertLoggable est une interface personnalisée qui répertorie simplement les propriétés/colonnes d'intérêt pour l'interception.

using System; 
using System.Reflection; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using NHibernate; 

    public class InsertDefaults : EmptyInterceptor { 
     private const string CREATED_BY = "CreatedById"; 

     private Hashtable GetInsertLoggablePropertyIndexes(string[] Properties) { 
      Hashtable result = new Hashtable(); 
      for (int i = 0; i < Properties.Length; i++) { 
       if (Properties[i] == CREATED_BY) { 
        result.Add(CREATED_BY, i); 
        break; 
       } 
      } 
      return result; 
     } 

     public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types) { 
      if (entity is IInsertLoggable) { 
       Hashtable indexes = GetInsertLoggablePropertyIndexes(propertyNames); 
       state[(int)indexes[CREATED_BY]] = currentUser; 
       PropertyInfo createdByProp = entity.GetType().GetProperty(CREATED_BY); 
       if (createdByProp != null) 
        createdByProp.SetValue(entity, currentUser, null); 
      } 
      return base.OnSave(entity, id, state, propertyNames, types); 
     } 
    } 

À mon avis, ce genre d'opération de déclenchement classique devrait probablement vivre sur la base de données et je partirais avec la première option ...