我正在尝试确定我是否正在使用SQL和DBIx :: Class接近以下问题,因为我对这两者都很新。
我有一个包含3个表的模式,设备,对象和网络
设备可以有0..1到多个对象 一个对象可以有1个网络但网络可以属于0 ...许多设备。
我试图在图片中显示的架构中捕获这种关系。
这是相关的Schema。
__PACKAGE__->table("Device");
__PACKAGE__->add_columns(
"devicename",
{ data_type => "varchar", is_nullable => 0, size => 50 },
"devicetype",
{ data_type => "varchar", is_nullable => 0, size => 20 },
"deviceid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
);
__PACKAGE__->set_primary_key("deviceid");
__PACKAGE__->has_many(
"objects",
"TestApp::Schema::Result::Object",
{ "foreign.device_deviceid" => "self.deviceid" },
{ cascade_copy => 0, cascade_delete => 0 },
__PACKAGE__->table("Object");
__PACKAGE__->add_columns(
"objectid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"objectname",
{ data_type => "varchar", is_nullable => 0, size => 100 },
"objecttype",
{ data_type => "varchar", is_nullable => 0, size => 20 },
"device_deviceid",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
"network_networkid",
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
);
__PACKAGE__->set_primary_key("objectid");
__PACKAGE__->belongs_to(
"device_deviceid",
"TestApp::Schema::Result::Device",
{ deviceid => "device_deviceid" },
{ is_deferrable => 1, on_delete => "NO ACTION", on_update => "NO ACTION" },
);
__PACKAGE__->belongs_to(
"network_networkid",
"TestApp::Schema::Result::Network",
{ networkid => "network_networkid" },
{
is_deferrable => 1,
join_type => "LEFT",
on_delete => "NO ACTION",
on_update => "NO ACTION",
},
);
__PACKAGE__->table("network");
__PACKAGE__->add_columns(
"networkid",
{ data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
"network",
{ data_type => "varchar", is_nullable => 1, size => 15 },
"netmask",
{ data_type => "varchar", is_nullable => 1, size => 15 },
"cidr",
{ data_type => "integer", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("networkid");
__PACKAGE__->has_many(
"objects",
"TestApp::Schema::Result::Object",
{ "foreign.network_networkid" => "self.networkid" },
{ cascade_copy => 0, cascade_delete => 0 },
);
对于我的测试数据,我正在插入如下所示的数据。有更有效的方法吗?
#get result sets
my $network_rs = $schema->resultset('Network');
my $device_rs = $schema->resultset('Device');
#create a new device
my $new_device = $device_rs->create( { devicename => 'test_device', devicetype => 'test_dt'});
#create a new network if it doesn't exist.
my $new_network = $network_rs->find_or_create({ network => '1.1.1.1', netmask => '255.255.255.0', cidr => '24' });
#Add two objects and set the foreign key for the network table for the newly created network above.
$new_device->objects->create( { objectname => 'networkobj1',network_networkid => $new_network->networkid });
$new_device->objects->create( { objectname => 'networkobj2',network_networkid => $new_network->networkid });
要查看分配给每个网络的网络,我只需执行以下操作;
my @deviceObjects = $new_device->objects();
foreach my $object (@deviceObjects)
{
print $object->objectname . " contains the following network:\n";
print $object->network_networkid->network . "\n";
print $object->network_networkid->netmask . "\n";
print $object->network_networkid->cidr . "\n";
}
答案 0 :(得分:3)
基本上你做的一切都是正确的。 您的对象表通常称为桥接器或多对多辅助表。 要直接从设备到其网络,您可以添加many_to_many帮助器方法,请参阅DBIx :: Class :: Relationship文档。 有一些模块可以用(测试)数据填充数据库,例如DBIx :: Class :: Fixtures。
对于返回单行(belongs_to,has_one和might_have)的关系以及返回a行列表(has_many)。 使用device-> objects->网络读取更加自然,包括存储外键的列的名称没有多大意义。
除了那些小事,还有一个好的开始! 在irc.perl.org中加入#dbix-class以获得实时帮助。
答案 1 :(得分:0)
重新插入测试数据,有一种更有效的方式(编写它),DBIC可以根据你告诉它的关系一次完成一大堆插入,我们称之为“multireate”,所以使用你的例子:
# get main device resultset:
my $device_rs = $schema->resultset('Device');
# create all the things:
$device_rs->create({
# Device columns:
devicename => 'test_device',
devicetype => 'test_dt',
# Objects:
objects => [
{
objectname => 'networkobj1',
# network for this object:
network_networkid => {
network => '1.1.1.1', netmask => '255.255.255.0', cidr => '24',
}
},
{
objectname => 'networkobj2',
# network for this object:
network_networkid => {
network => '1.1.1.1', netmask => '255.255.255.0', cidr => '24',
}
}
]
});
请注意,指定网络数据不应该为您提供两个插入的网络行,它将使用find_or_new来创建该行,因此应找到为第二个创建的第一个行。