使用 CleanUp 后 SubSonic 3 Linq 加入错误

发布于 2024-09-15 03:41:14 字数 900 浏览 2 评论 0原文

我正在使用 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 位于 pastebin

I am using the ActiveRecord SubSonic3 templates. Everything was working just dandy, then I decided I wanted things to look a bit better. See my database has field that look like this:

SomeKey_id
SomeOtherKey_id

I wanted to clean it up so that it would instead be

SomeKeyID
SomeOtherKeyID

when accessing it through SubSonic.

So I added this small thing to the CleanUp function of settings.ttinclude

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

Now though everywhere I have joins on an ID field it no longer works.

For example:

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

Does not work.

It will yield this exception:

The member 'FooID' is not supported

However before I did the _id fix it worked perfectly. What is wrong? How do I work around this?

Stacktrace is at pastebin

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゝ杯具 2024-09-22 03:41:14

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

What does the CleanUp function run on? Does it run on the output of the code templates, i.e. the auto-generated C# code that SubSonic generates? Surely you need this auto-generated code to refer to the correct database columns that you are accessing. If your database column is actually called SomeKey_id and you change that to SomeKeyID in the code, then of course SubSonic will be unable to locate that database column. In other words, how are you making sure that you are replacing only the identifiers that you will be using in C# code, but not the identifiers that refer to the database columns?

遇见了你 2024-09-22 03:41:14

正如我怀疑的那样,问题出在 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

编辑:

实际上它比这更复杂。我最终必须向 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],

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

The problem was in SubSonic.Core as I suspected. I downloaded the source for it and in Schema/DatabaseTable.cs I had to change the GetColumnByPropertyName function to something like this:

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;
}

The reason for this is that when it tries to resolve the column name to an IColumn in the appropriate table all it has is something like "FooID" and all the columns have a .Name of "Foo_id". So, I made it so that if it doesn't find the column the first time then it will run the CleanUp function the second time on each of the column names so that it can find a match.

If someone from SubSonic reads this, I'd love if you somehow patched this bug or at least gave notice of it. Note the version I'm using(and the source I'm using) is 3.0.0.4

EDIT:

Actually it's more complicated than this. I ended up having to add a CleanName field to IColumn and DataColumn in SubSonic and then fill in the CleanName from when the T4 templates run. Then I changed the line above to something like

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

Then in lots of random places I had to change code like this:

ParameterValue = settings[tbl.PrimaryKey.Name],

to code like this:

ParameterValue = settings[tbl.PrimaryKey.CleanName],

I'm still not sure that I've gotten all the changes complete but I can update, insert, select, and join so I'd say I'm close if not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文