使用CleanUp后,SubSonic 3 Linq加入错误

时间:2010-08-19 20:57:08

标签: c# .net linq subsonic subsonic3

我正在使用ActiveRecord SubSonic3模板。一切都工作得很花哨,然后我觉得我希望事情看起来好一点。请参阅我的数据库具有如下所示的字段:

SomeKey_id
SomeOtherKey_id

我想清理一下,以便它可以

SomeKeyID
SomeOtherKeyID

通过SubSonic访问时。

所以我将这个小东西添加到settings.ttinclude

的CleanUp函数中
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

2 个答案:

答案 0 :(得分:0)

CleanUp功能运行的是什么?它是否在代码模板的输出上运行,即SubSonic生成的自动生成的C#代码?当然,您需要使用此自动生成的代码来引用您正在访问的正确数据库列。如果您的数据库列实际上被称为SomeKey_id并且您在代码中将其更改为SomeKeyID,那么当然SubSonic将无法找到该数据库列。换句话说,您如何确保仅替换将在C#代码中使用的标识符,但引用数据库列的标识符?

答案 1 :(得分:0)

问题出现在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的某人读到这篇文章,我会很高兴,如果你以某种方式修补了这个bug或者至少注意到了它。请注意我正在使用的版本(以及我正在使用的源代码)是3.0.0.4

修改

实际上它比这更复杂。我最终必须在SubSonic中向IColumn和DataColumn添加一个CleanName字段,然后在运行T4模板时填写CleanName。然后我将上面的行改为

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

然后在很多随机的地方我不得不改变这样的代码:

ParameterValue = settings[tbl.PrimaryKey.Name],

代码如下:

ParameterValue = settings[tbl.PrimaryKey.CleanName],

我仍然不确定我是否完成了所有更改,但我可以更新,插入,选择和加入,所以我会说如果没有,我会很接近。