2010-08-19 2 views
1

Я использую шаблоны ActiveScripts SubSonic3. Все работало просто денди, тогда я решил, что мне нужно, чтобы все выглядело немного лучше. Смотрите мою базу данных имеет поле, которое выглядит следующим образом:SubSonic 3 Linq Ошибка соединения после использования CleanUp

SomeKey_id 
SomeOtherKey_id 

Я хотел, чтобы очистить его так, чтобы он вместо этого будет

SomeKeyID 
SomeOtherKeyID 

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

Поэтому я добавил эту маленькую вещь, к функции зачистка 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 является at pastebin

+0

Это, вероятно, не связано с вашей проблемой, но ваше регулярное выражение неверно. Если у вас есть что-то, называемое 'my_idea', то регулярное выражение будет соответствовать, а затем вы замените' dea' на 'ID', получив' my_iID'. Попробуйте использовать regex '' _id $ "' вместо этого, или даже лучше, просто скажите 'if (result.EndsWith (" _ id ", StringComparison.OrdinalIgnoreCase)). – Timwi

+0

@ Тим, да, несвязанный, но спасибо, что работает намного лучше! – Earlz

ответ

0

Проблема была в SubSonic.Core, как я подозревал. Я скачал источник для него и в схеме/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], 

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

+0

Примечание. Я сделал проблему в SubSonic об этом: http: // github.com/subsonic/SubSonic-3.0/issues/issue/222/ – Earlz

0

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

+0

CleanUp является фактической функцией в шаблоне T4. Поэтому, когда он генерирует код, он будет запускать CleanUp для определенных вещей, таких как имена столбцов и таблиц. Он имеет два разных «имени». Он имеет имя CleanName, которое является именем .Net, и оно имеет имя, которое является именем столбца базы данных. Это влияет только на CleanName, которое предположительно должно быть только для эстетических целей. – Earlz

+0

ОК, и я полагаю, вы просмотрели код, который был создан из шаблона, и проверили, что все идентификаторы C# были заменены, и все имена столбцов DB по-прежнему без изменений? – Timwi

+0

@Tim Я не вижу никаких проблем с кодом, который он генерирует. – Earlz