SubSonic 3 Linq Ошибка соединения после использования CleanUp - PullRequest
1 голос
/ 20 августа 2010

Я использую шаблоны ActiveRecord SubSonic3.Все работало просто замечательно, потом я решил, что хочу, чтобы все выглядело немного лучше.Посмотрите в моей базе данных есть поле, которое выглядит так:

SomeKey_id
SomeOtherKey_id

Я хотел очистить его, чтобы вместо него было

SomeKeyID
SomeOtherKeyID

при доступе к нему через SubSonic.

Итак, я добавил эту маленькую вещь в функцию CleanUp settings.ttinclude

if(Regex.IsMatch(result,".*_id",RegexOptions.IgnoreCase)){
  result=result.Substring(0,result.Length-3);
  result+="ID";
}

Теперь, несмотря на то, что везде у меня есть соединения в поле ID, оно больше не работает.

Например:

var data=from f in Foo
         join b in Bar on f.FooID equals b.FooID
         select new{FooValue=f, BarValue=b};

Не работает.

Будет выдано следующее исключение:

Элемент 'FooID' не являетсяподдерживается

Однако до того как я исправил _id, он работал отлично.Что случилось?Как мне обойти это?

Stacktrace составляет в пасте

Ответы [ 2 ]

0 голосов
/ 20 августа 2010

Проблема была в SubSonic.Core, как я и подозревал. Я скачал исходный код для него и в Schema / DatabaseTable.cs мне пришлось изменить функцию GetColumnByPropertyName на что-то вроде этого:

public IColumn GetColumnByPropertyName(string PropertyName)
{
    var c = Columns.SingleOrDefault(x => x.Name.Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase));
    if (c == null)
    {
        c=Columns.SingleOrDefault(x => CleanUpColumnName(x.Name).Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase));
        if (c == null)
        {
            throw new NotSupportedException("Couldn't find column name");
        }
    }
    return c;
}
private string CleanUpColumnName(string name)
{
    //don't forget to change Settings.ttinclude:CleanUp when changing this function! 
    string result = name;
    if (result.EndsWith("_id", StringComparison.OrdinalIgnoreCase))
    {
        result = result.Substring(0, result.Length - 3);
        result += "RID";
    }
    return result;
}

Причина этого в том, что когда он пытается преобразовать имя столбца в IColumn в соответствующей таблице, все, что у него есть, это что-то вроде «FooID», и все столбцы имеют .Name «Foo_id». Итак, я сделал так, что если он не найдет столбец в первый раз, тогда он будет запускать функцию CleanUp во второй раз для каждого из имен столбцов, чтобы он мог найти совпадение.

Если кто-то из SubSonic прочитает это, я бы хотел, чтобы вы как-то исправили эту ошибку или хотя бы уведомили об этом. Обратите внимание, что версия, которую я использую (и источник, который я использую) - 3.0.0.4

EDIT:

На самом деле все сложнее, чем это. В итоге мне пришлось добавить поле CleanName в IColumn и DataColumn в SubSonic, а затем заполнить CleanName с момента запуска шаблонов T4. Затем я изменил строку выше на что-то вроде

var c = Columns.SingleOrDefault(x => x.CleanName.Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase));

Тогда во многих случайных местах мне приходилось менять код следующим образом:

ParameterValue = settings[tbl.PrimaryKey.Name],

кодировать как это:

ParameterValue = settings[tbl.PrimaryKey.CleanName],

Я все еще не уверен, что все изменения были завершены, но я могу обновить, вставить, выбрать и присоединиться, поэтому я бы сказал, что я близок, если нет.

0 голосов
/ 20 августа 2010

На что работает функция CleanUp? Работает ли он на выходе шаблонов кода, то есть автоматически сгенерированного кода C #, который генерирует SubSonic? Конечно, вам нужен этот автоматически сгенерированный код для ссылки на правильные столбцы базы данных, к которым вы обращаетесь. Если ваш столбец базы данных на самом деле называется SomeKey_id и вы измените его на SomeKeyID в коде, то, конечно, SubSonic не сможет найти этот столбец базы данных. Другими словами, как вы убедитесь, что заменяете только те идентификаторы, которые вы будете использовать в коде C #, но , а не идентификаторы, которые относятся к столбцам базы данных?

...