形成正确的 DBIx::Class 语法来连接表,其中外键存储在不同外部表的一对一连接中

问题描述 投票:0回答:1

我一直在阅读文档并尝试一些事情,但我似乎无法想出创建关系所需的语法。我在这里简化了我的需求:

Table: thing  
Field: thingID  
Field: sprocketID  
Field: thingWidth  
(there are more fields)  

Table: sprocket  
Field: sprocketID  
Field: sprocketLength  
(there are more fields)  

Table: cog  
Field: sprocketLength  
Field: thingWidth  
Field: cogPartNum  

我正在尝试建模。

  • 每件事物都有一个链轮。多个事物可以具有相同的链轮,这就是为什么我想将 sprocketLength(以及有关链轮的其他信息)存储在链轮表中,而不是在事物表中重复该信息。多个链轮可以具有相同的长度。
  • 每件事物都有一个齿轮——您需要链轮的链轮长度并且 从事物的 thingWidth 来确定哪个齿轮(以及哪个 cogPartNum)。

以下 SQL 获取我正在寻找的值:

SELECT * FROM thing
    JOIN sprocket ON thing.sprocketID = sprocket.sprocketID
    JOIN cog ON sprocket.sprocketLength = cog.sprocketLength AND thing.thingWidth = cog.thingWidth
    WHERE thing.thingID = ?;

我有一些看起来像这样的代码,但我不确定如何正确定义我的条件(齿轮关系定义上的第三个参数):

My::Schema::Thing->has_one('sprocket' => 'My::Schema::Sprocket', 'sprocketID');
My::Schema::Thing->has_one('cog' => 'My::Schema::Cog', {
    'foreign.thingWidth' => 'self.thingWidth',
    'foreign.sprocketLength' => *??????       # this is where I'm getting confused because sprocketLength isn't in self*
});

所以我想我可能需要使用 cond 的 coderef 定义,但我正在努力让它发挥作用。我有一些看起来像这样的东西:

My::Schema::Thing->has_one('cog' => 'My::Schema::Cog', sub {
    my $args = shift;
    return {
        "$args->{foreign_alias}.thingWidth" => { -ident => "$args->{self_alias}.thingWidth" },
        "$args->{foreign_alias}.sprocketLength" => $self->{self_result_object}->sprocket->sprocketLength,
    };
});

但这似乎对我不起作用。我正在尝试调用 $self->cog->cogPartNum 来访问我的主代码中某件事的 cogPartNum 。我正在经历 coderef 的多次执行(确切地说是 3 次),最后一次没有定义 $self->{self_result_object} ,所以 我在尝试访问 undef 的 sprocket 方法时遇到错误。

更新:通过使用 DBIx::Class::Relationship::Base 的 perldoc 中的一些代码示例,我已经更接近了一些,尽管我仍然不完全理解它。返回中的第二个值与“无连接”情况有关。这似乎可行,但如果我想使用连接情况(第一个返回值)来预取我的值,下面的代码仍然会失败。

sub {
    my $args = shift;
 
    return (
        {
            "$args->{foreign_alias}.thingWidth" => { -ident => "$args->{self_alias}.thingWidth" },
            "$args->{foreign_alias}.sprocketLength" => $self->{self_result_object}->sprocket->sprocketLength,   # this is why it fails
        },
        ! $args->{self_result_object} ? () : {
            "$args->{foreign_alias}.thingWidth" => $args->{self_result_object}->thingWidth,
            "$args->{foreign_alias}.sprocketLength" => $args->{self_result_object}->sprocketLength,
        },
        (),
    );
}

您有什么指导吗?请原谅任何拼写错误,因为我只是凭记忆打出这些内容。

perl orm foreign-keys dbix-class
1个回答
1
投票

您的

sprocket
cog
关系应该是
belongs_to
:

__PACKAGE__->belongs_to('sprocket' => 'My::Schema::Sprocket', 'sprocketID');

要使其工作,您需要加入链轮关系。据我所知,DBIC 不提供在涉及关系时添加连接的方法。

你在正确的轨道上使用

-ident
,基本上它所做的就是将其值传递给生成的SQL,所以如果你确保链轮关系已连接,这样的事情应该可以工作:

__PACKAGE__->belongs_to('cog' => 'My::Schema::Cog', sub {
    my $args = shift;
    return {
        "$args->{foreign_alias}.thingWidth" => { -ident => "$args->{self_alias}.thingWidth" },
        "$args->{foreign_alias}.sprocketLength" => { -ident => "sprocket.sprocketLength" },
    };
});

在 ResultSet 和/或 Result 类上拥有一个执行此操作的方法将是我的首选方法。 我在所有返回 ResultSet 或 Result 对象数组的方法前面加上

search_

© www.soinside.com 2019 - 2024. All rights reserved.