簡體   English   中英

LinqToSQL外鍵實體到字符串的通用查找

[英]LinqToSQL generic lookup of foreign key entity to string

我正在使用Linq To Sql,正在嘗試保留更改歷史記錄並存儲這些數據庫。

我知道這里有諸如DoddleAudit之類的框架,但是對我來說,它感覺有點過時且過分膨脹,因此我正在嘗試創建自己的框架。

這就是到目前為止。 我正在尋找一種使重復代碼更可重用的方法:

protected void InsertAuditRecordToDatabase(ModifiedMemberInfo[] changes, object entity) 
{
    Type type = entity.GetType();
    PropertyInfo key;
    key = type.GetProperties()
        .Where(o => 
            o.GetCustomAttributes(typeof(ColumnAttribute), true)
                .Any(a=>((ColumnAttribute)a).IsPrimaryKey)).SingleOrDefault();

    AuditRecord audit = new AuditRecord();
    audit.Action = (byte)AuditAction.Update;
    audit.AuditDate = DateTime.Now;
    audit.AssociationTable = null;
    audit.AssociationTableKey = null;
    audit.EntityTable = type.Name;
    audit.EntityTableKey = int.Parse(key.GetValue(entity, null).ToString());

    audit.UserName = HttpContext.Current.User.Identity.Name;
    if (string.IsNullOrEmpty(audit.UserName))
        audit.UserName = "Anonymous";

    foreach (ModifiedMemberInfo mmi in changes)
    {
        AuditRecordField field = new AuditRecordField();
        if (!excludedFieldNamesFromAudit.Any(x => x.Equals(mmi.Member.Name, StringComparison.OrdinalIgnoreCase)))
        {
            field.MemberName = mmi.Member.Name;

            field.OldValue = (mmi.OriginalValue != null ? mmi.OriginalValue.ToString() : string.Empty);
            field.NewValue = (mmi.CurrentValue != null ? mmi.CurrentValue.ToString() : string.Empty);

            if ((field.OldValue != null && !field.OldValue.Equals(field.NewValue)) ||
                (field.OldValue == null && field.NewValue != null))
            {
                // Special handling
                if (field.MemberName.Equals("EUAMemberTypeId"))
                {
                    int oldInt;
                    OrganisationSubType oldValue = null;
                    if(int.TryParse(field.OldValue, out oldInt))
                        oldValue = this.OrganisationSubTypes.SingleOrDefault(m => m.Id == oldInt);
                    field.OldValue = oldValue != null ? oldValue.Name : string.Empty;

                    int newInt;
                    OrganisationSubType newValue = null;
                    if(int.TryParse(field.NewValue, out newInt))
                        newValue = this.OrganisationSubTypes.SingleOrDefault(m => m.Id == newInt);
                    field.NewValue = newValue != null ? newValue.Name : string.Empty;
                }

                if (field.MemberName.Equals("ContactPersonStaffId"))
                {
                    int oldInt;
                    OrganisationStaff oldValue = null;
                    if (int.TryParse(field.OldValue, out oldInt))
                        oldValue = this.OrganisationStaffs.SingleOrDefault(m => m.Id == oldInt);
                    field.OldValue = oldValue != null ? oldValue.Contact.FullName : string.Empty;

                    int newInt;
                    OrganisationStaff newValue = null;
                    if (int.TryParse(field.NewValue, out newInt))
                        newValue = this.OrganisationStaffs.SingleOrDefault(m => m.Id == newInt);
                    field.NewValue = newValue != null ? newValue.Contact.FullName : string.Empty;
                }

                if (field.MemberName.Equals("CountryId"))
                {
                    int oldInt;
                    Country oldValue = null;
                    if (int.TryParse(field.OldValue, out oldInt))
                        oldValue = this.Countries.SingleOrDefault(m => m.Id == oldInt);
                    field.OldValue = oldValue != null ? oldValue.Name : string.Empty;

                    int newInt;
                    Country newValue = null;
                    if (int.TryParse(field.NewValue, out newInt))
                        newValue = this.Countries.SingleOrDefault(m => m.Id == newInt);
                    field.NewValue = newValue != null ? newValue.Name : string.Empty;
                }

                // Save it to the DB
                audit.AuditRecordFields.Add(field);
            }
        }
    }

    if (audit.AuditRecordFields.Count > 0)
        this.AuditRecords.InsertOnSubmit(audit);
}

如您所見,此代碼塊正在重復:

if (field.MemberName.Equals("CountryId"))
{
    int oldInt;
    Country oldValue = null;
    if (int.TryParse(field.OldValue, out oldInt))
        oldValue = this.Countries.SingleOrDefault(m => m.Id == oldInt);
    field.OldValue = oldValue != null ? oldValue.Name : string.Empty;

    int newInt;
    Country newValue = null;
    if (int.TryParse(field.NewValue, out newInt))
        newValue = this.Countries.SingleOrDefault(m => m.Id == newInt);
    field.NewValue = newValue != null ? newValue.Name : string.Empty;
}

重復的模式是:

  • 在某個表上查找: Countries
  • 尋找特定實體: Country
  • 使用某個表達式: m => m.ID == oldInt
  • 另一個將實體轉換為字符串的表達式: oldValue.Name

我希望可以用一些通用的表達魔術來做到這一點,但我似乎無法弄清楚。

這應該按照您的預期工作。

您面臨的挑戰之一是您希望在解析字符串時創建變量之前就擁有int參數的表達式。 如果在創建表達式時已經創建了變量,則可以引用該變量,這樣您的過程將更加簡單。

我通過在將字符串解析為int變量后動態構建一個表達式來解決這個問題。

    protected void InsertAuditRecordToDatabase(ModifiedMemberInfo[] changes, object entity)
    {
        Type type = entity.GetType();
        PropertyInfo key;
        key = type.GetProperties()
            .Where(o =>
                o.GetCustomAttributes(typeof(ColumnAttribute), true)
                    .Any(a => ((ColumnAttribute)a).IsPrimaryKey)).SingleOrDefault();

        AuditRecord audit = new AuditRecord();
        audit.Action = (byte)AuditAction.Update;
        audit.AuditDate = DateTime.Now;
        audit.AssociationTable = null;
        audit.AssociationTableKey = null;
        audit.EntityTable = type.Name;
        audit.EntityTableKey = int.Parse(key.GetValue(entity, null).ToString());

        audit.UserName = HttpContext.Current.User.Identity.Name;
        if (string.IsNullOrEmpty(audit.UserName))
            audit.UserName = "Anonymous";

        foreach (ModifiedMemberInfo mmi in changes)
        {
            AuditRecordField field = new AuditRecordField();
            if (!excludedFieldNamesFromAudit.Any(x => x.Equals(mmi.Member.Name, StringComparison.OrdinalIgnoreCase)))
            {
                field.MemberName = mmi.Member.Name;

                field.OldValue = (mmi.OriginalValue != null ? mmi.OriginalValue.ToString() : string.Empty);
                field.NewValue = (mmi.CurrentValue != null ? mmi.CurrentValue.ToString() : string.Empty);

                if ((field.OldValue != null && !field.OldValue.Equals(field.NewValue)) ||
                    (field.OldValue == null && field.NewValue != null))
                {
                    // Special handling
                    if (field.MemberName.Equals("EUAMemberTypeId"))
                    {
                        field.OldValue = GetDescription(this.OrganisationSubTypes, field.OldValue, m => m.Id, m => m != null ? m.Name : string.Empty);
                        field.NewValue = GetDescription(this.OrganisationSubTypes, field.NewValue, m => m.Id, m => m != null ? m.Name : string.Empty);
                    }

                    if (field.MemberName.Equals("ContactPersonStaffId"))
                    {
                        field.OldValue = GetDescription(this.OrganisationStaffs, field.OldValue, m => m.Id, m => m != null ? m.Contact.FullName : string.Empty);
                        field.NewValue = GetDescription(this.OrganisationStaffs, field.NewValue, m => m.Id, m => m != null ? m.Contact.FullName : string.Empty);
                    }

                    if (field.MemberName.Equals("CountryId"))
                    {
                        field.OldValue = GetDescription(this.Countries, field.OldValue, m => m.Id, m => m != null ? m.Name : string.Empty);
                        field.NewValue = GetDescription(this.Countries, field.NewValue, m => m.Id, m => m != null ? m.Name : string.Empty);
                    }

                    // Save it to the DB
                    audit.AuditRecordFields.Add(field);
                }
            }
        }

        if (audit.AuditRecordFields.Count > 0)
            this.AuditRecords.InsertOnSubmit(audit);
    }

    public static string GetDescription<T, TProp>(Table<T> thisTable, string searchParam, Expression<Func<T, TProp>> searchExpression, Expression<Func<T, string>> descriptionExpression)
        where T : class
    {
        if (!(searchExpression.Body is MemberExpression))
        {
            throw new ArgumentException("Search Expression must be a MemberExpression (i.e v => v.Id)", "searchExpression");
        }
        else
        {
            int searchValue;
            if (int.TryParse(searchParam, out searchValue))
            {
                var equalityExpression = Expression.Equal(searchExpression.Body, Expression.Constant(searchValue));
                var lambdaExpression = Expression.Lambda<Func<T, bool>>(equalityExpression, searchExpression.Parameters);

                // the passed-in expression must resemble v => v.Id
                // the generated expression will resemble v => v.Id == 5

                var value = thisTable.SingleOrDefault(lambdaExpression);
                return descriptionExpression.Compile()(value);
            }

            return string.Empty;
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM