الحصول على الدرجة أسماء الحقول و عمود الجدول أسماء من NHibernate البيانات الوصفية

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

  •  05-07-2019
  •  | 
  •  

سؤال

الخلفية

أنا باستخدام إرثا قاعدة البيانات مع جميع أنواع القبيح الزوايا.بت واحد هو التدقيق.هناك جدول قائمة tablename/مجال تركيبات من الحقول التي يجب أن مراجعة الحسابات.على سبيل المثال, إذا كان هناك صف يحتوي على "أوامر العمل" اسم الجدول و "المركز" بالنسبة fieldname, ثم كنت بحاجة إلى إضافة صف(s) إلى مراجعة الجدول كلما أمر العمل.حالة العقار التغييرات في التطبيق.أنا أعرف النهج:NH الأحداث أو اعتراضية ، ولكن لدي مشكلة في معرفة قبل أن نصل إلى هذه المرحلة.

السؤال

ما أريد أن أعرفه هو كيفية الحصول على قائمة من أزواج مفتاح/قيمة واحدة ثابتة الطبقة التي تحتوي على (أ) قاعدة البيانات اسم الحقل (ب) يرتبط اسم الخاصية في الصف.حتى بلدي على سبيل المثال ، لدى فئة تسمى أوامر العمل المرتبطة جدول يسمى (ليس من المستغرب) أمر العمل.لدي المنشأة على أن أوامر العمل فئة تسمى CurrentStatus.مطابقة المنشأة في أمر العمل الجدول هو الوضع.لاحظ التناقض بين الملكية اسم الجدول عمود الاسم ؟ أريد أن أعرف اسم الخاصية إلى الوصول قبل وبعد بيانات مراجعة الحسابات.ولكن أنا أيضا بحاجة إلى معرفة النسخ اسم العمود بحيث لا يمكن الاستعلام غبي إرث "AuditTheseColumns" الجدول.

ما حاولت

في تطبيق تغيير أوامر العمل.CurrentStatus من "TS" إلى "IP".أنظر في هذه المراجعة تتبع الجدول نرى أن أمر العمل.عمود الحالة يتم تعقب.وذلك بعد استدعاء الدورة.SaveOrUpdate(أمر العمل), كنت بحاجة إلى العثور على أوامر العمل الممتلكات المرتبطة عمود الحالة و هل الدورة.حفظ(auditRecord) تقول القديمة ("TS") و الجديد ("IP") القيم.

بقدر ما استطيع ان اقول ، يمكنك الحصول على معلومات حول فئة:

        var fieldNames = new List<string>();
        IClassMetadata classMetadata = SessionFactory(Resources.CityworksDatasource).GetClassMetadata(typeof(T));
        int propertyCount = 0;
        foreach (IType propertyType in classMetadata.PropertyTypes)
        {
            if (propertyType.IsComponentType)
            {
                var cp = (ComponentType)propertyType;

                foreach (string propertyName in cp.PropertyNames)
                {
                    fieldNames.Add(propertyName);
                }
            }
            else if(!propertyType.IsCollectionType)
            {
                fieldNames.Add(classMetadata.PropertyNames[propertyCount + 1]);
            }

            propertyCount++;
        }

والمعلومات حول الجدول:

        var columnNames = new List<string>();
        PersistentClass mappingMeta = ConfigureCityworks().GetClassMapping(typeof(T));

        foreach (Property property in mappingMeta.PropertyIterator)
        {
            foreach (Column selectable in property.ColumnIterator)
            {
                if (columnNames.Contains(selectable.Name)) continue;
                columnNames.Add(selectable.Name);
            }
        }

ولكن ليس في نفس الوقت.أي أفكار ؟ أنا في حيرة من أين للبحث المقبل.

هل كانت مفيدة؟

المحلول

الآن إذا فهمت بشكل صحيح هنا هو ما يمكنك فعله....

طريقة واحدة أن قراءة وتحليل الخرائط XML ملفات dll التي هي جزء لا يتجزأ من قبل أو حتى بعد NHibernate الدورة مصنع بناء.بهذه الطريقة يمكنك الحصول على كل المعلومات التي تحتاج من ملفات XML (مع عمود يتوافق مع أي الملكية) و تعبئة العالمية (ربما ثابت) مجموعة من الكائنات المخصصة التي سوف تعقد الكيان اسم القاموس مع مفتاح وبربري اسم و قيمة اسم العمود (أو العكس).

يمكنك ثم الوصول إلى العالمية هذه المجموعة للحصول على المعلومات التي تحتاج إليها مباشرة بعد الدعوة إلى SaveOrUpdate() كما وصفته.الجانب السلبي لهذا النهج هو أن تحتاج إلى كتابة الخاصة بك تحليل XML المنطق retrive المعلومات التي تحتاج إليها من الخرائط XML الملفات.

ويكون البديل هو إنشاء سمة مخصصة لتزيين كل الممتلكات الخاصة بك الكيانات من أجل الحصول على اسم العمود الذي يتوافق مع كل خاصية.على سبيل المثال سيكون:

[ColumnName("MyColumn")]
public string Status { get; set; }

باستخدام انعكاس يمكنك بسهولة الحصول على العقار الاسم من السمة العمود اسم هذا العقار تعيين.

الجانب السلبي من هذا النهج سوف يكون لها للحفاظ على مزامنة أسماء الأعمدة مع قيم السمة عندما مخطط قاعدة البيانات يتم تحديثها.

نصائح أخرى

كيفية الحصول على قاعدة بيانات العمود / أسماء الحقول والطبقة الملكية أسماء الكيان المعين من قبل NHibernate:

using System;
using System.Collections.Generic;
using System.Reflection;
using NHibernate;
using NHibernate.Persister.Entity;

namespace Stackoverflow.Example
{
    /// <summary>
    /// NHibernate helper class
    /// </summary>
    /// <remarks>
    /// Assumes you are using NHibernate version 3.1.0.4000 or greater (Not tested on previous versions)
    /// </remarks>
    public class NHibernateHelper
    {
        /// <summary>
        /// Creates a dictionary of property and database column/field name given an
        /// NHibernate mapped entity
        /// </summary>
        /// <remarks>
        /// This method uses reflection to obtain an NHibernate internal private dictionary.
        /// This is the easiest method I know that will also work with entitys that have mapped components.
        /// </remarks>
        /// <param name="sessionFactory">NHibernate SessionFactory</param>
        /// <param name="entity">An mapped entity</param>
        /// <returns>Entity Property/Database column dictionary</returns>
        public static Dictionary<string, string> GetPropertyAndColumnNames(ISessionFactory sessionFactory, object entity)
        {
            // Get the objects type
            Type type = entity.GetType();

            // Get the entity's NHibernate metadata
            var metaData = sessionFactory.GetClassMetadata(type.ToString());

            // Gets the entity's persister
            var persister = (AbstractEntityPersister)metaData;

            // Creating our own Dictionary<Entity property name, Database column/filed name>()
            var d = new Dictionary<string, string>();

            // Get the entity's identifier
            string entityIdentifier = metaData.IdentifierPropertyName;

            // Get the database identifier
            // Note: We are only getting the first key column.
            // Adjust this code to your needs if you are using composite keys!
            string databaseIdentifier = persister.KeyColumnNames[0];

            // Adding the identifier as the first entry
            d.Add(entityIdentifier, databaseIdentifier);

            // Using reflection to get a private field on the AbstractEntityPersister class
            var fieldInfo = typeof(AbstractEntityPersister)
                .GetField("subclassPropertyColumnNames", BindingFlags.NonPublic | BindingFlags.Instance);

            // This internal NHibernate dictionary contains the entity property name as a key and
            // database column/field name as the value
            var pairs = (Dictionary<string, string[]>)fieldInfo.GetValue(persister);

            foreach (var pair in pairs)
            {
                if (pair.Value.Length > 0)
                {
                    // The database identifier typically appears more than once in the NHibernate dictionary
                    // so we are just filtering it out since we have already added it to our own dictionary
                    if (pair.Value[0] == databaseIdentifier)
                        break;

                    d.Add(pair.Key, pair.Value[0]);
                }
            }

            return d;
        }
    }
}

الاستخدام:

// Get your NHiberate SessionFactory wherever that is in your application
var sessionFactory = NHibernateHelper.SessionFactory;

// Get an entity that you know is mapped by NHibernate
var customer = new Customer();

// Get a dictionary of the database column / field names and their corresponding entity property names
var propertyAndColumnNamesDictionary =
    Stackoverflow.Example.NHibernateHelper.GetPropertyAndColumnNames(sessionFactory, customer);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top