Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Class::DBI vs. DBIx::Class

by hrr (Monk)
on Jun 24, 2006 at 21:08 UTC ( [id://557402]=perlquestion: print w/replies, xml ) Need Help??

hrr has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks:

Class::DBI and DBIx::Class both seem to be very nice modules for accessing relational databases in an object-oriented way. Both modules look rather similar and it is hard for me to decide which one I should use. It would be great, if you could advise me on this decision---generally I would prefer the more robust and stable solution.

So far, I tried to use Class::DBI and DBD::DB2 on ActivePerl. This works for fine for SELECTs; however, insert() does not work for some reason (Can't locate object method "insert"). When I use DBD::CSV, insert works. Alternatively, I could use perl on cygwin (but I have to find out how to compile DBD::DB2 there). Hints on this problem would also be appreciated!

Thank you,
Best,
Hansres

Update: Thanks for all these helpful comments! To summarize, the options are the following:
  • Class::DBI provides a straightforward interface; however, its features are somewhat limited.
  • DBIx::Class provides more general interfaces that allow greater flexibility and complexity; this comes at the cost of being slightly more difficult to get started. Furthermore, this module has an active development community
  • Rose::DB::Object provides a third alternative. It supports only a limited number of databases (DBD modules are not sufficient; e.g., DB2 is not supported).

Replies are listed 'Best First'.
Re: Class::DBI vs. DBIx::Class
by davidrw (Prior) on Jun 25, 2006 at 01:04 UTC
      Yes, indeed, create() works! Now I realize that I have used perl and perldoc on a different versions of Class::DBI...

      Also, the links are interessting. Apparently Rose::DB::Object seems to be a popular alternative to Class::DBI (although not in my case, as DB2 is not yet supported by Rose::DB).
Re: Class::DBI vs. DBIx::Class
by rafl (Friar) on Jun 25, 2006 at 11:16 UTC

    I strongly suggest using DBIx::Class.

    It learned a lot from the mistakes Class::DBI made and also has a vast amount of features Class::DBI doesn't have.

    My favourite is the concept of ResultSets. For example can put together your queries piece by piece:

    my $persons = $schema->resultset('Person'); my $active_persons = $person->search({ active => 1 });

    Now you can either iterate over the results of those two resultset..

    while (my $person = $person->next) { ...; }

    .. or get a list of objects, representing rows, back..

    my @person_objs = $person->all;

    .. or do further searches..

    $active_persons->search({ writeup_comment.title => 'Foo', }, { join => { writeup => 'writeup_comment' }, prefetch => 'writeup', }); # gets you all persons with have recieved a comment with the title 'Fo +o' for one of their writeups, for example

    .. or do a related_searche to get a resultset associated with another table or view, which are somehow connected to the current resultset:

    my $writeups = $active_persons->search_related('Writeup');

    Note that SQL statements are only executed when it's actually needed, which makes DBIx::Class quite performant.

    Even if DBIx::Class still misses some features one might expect (subqueries, triggers, ...) I think it's already quite stable and I use it for production in several places.

    Cheers, Flo

      Now I understand that DBIx::Class is more flexible than Class::DBI! On the other hand, this comes at the price of longer code for simple tasks, e.g., for inserting into a table 'Person', one would use
      # using DBIx::Class: $schema->resultset('Person')->new({FirstName=>'Joe'})->insert(); # using Class::DBI: DB::Person->insert({FirstName=>'Joe'});
      Nevertheless, the greater flexibility motivated me to try DBIx::Class, too. What still bothers me is that
      package DB::Person; use base 'DBIx::Class'; __PACKAGE__->load_components(qw/PK::Auto Core/); __PACKAGE__->table('T_PERSON'); __PACKAGE__->add_columns(qw[PersonId FirstName]); __PACKAGE__->set_primary_key('PersonId'); package DB; use base 'DBIx::Class::Schema'; __PACKAGE__->load_classes(qw[Person]);
      fails with Can't locate object method "result_source_instance" via package "DB/Person" (perhaps you forgot to load "DB/Person"?) at c:/Perl/site/lib/DBIx/Class/Schema.pm line 75. If I put the definition of DB::Person into DB/Person.pm, it works, but is far less elegant/compact. Is there a smarter solution?
        On the other hand, this comes at the price of longer code for simple tasks, e.g., for inserting into a table 'Person', one would use
        # using DBIx::Class: $schema->resultset('Person')->new({FirstName=>'Joe'})->insert(); # using Class::DBI: DB::Person->insert({FirstName=>'Joe'});

        How about:

        $schema->resultset('Person')->create({ FirstName => 'Joe' });

        If you don't want to get the resultset from the schema first, you'll need to use DBIx::Class (DBIC) without a schema, which is usually called CDBI plain, but you'll then loose the advantages of the composable schemas, which, for example, allow you to connect to multiple databases from the same set of classes. I think using schemas is usually worth the overhead.

        I don't really know how to solve your problem with the posted snippet, but I suspect it's caused by the load_classes call. You can probably work that around with using register_class or register_source, but I haven't really looked into that as I don't like to ram up a single .pm file with several modules.

        Cheers, Flo

Re: Class::DBI vs. DBIx::Class
by ioannis (Abbot) on Jun 25, 2006 at 00:57 UTC
      To me, the DBIx:: modules are more useful as facade interfaces to DBI, and the class::dbi modules are helpful to define relations between tables
      DBIx::Class does that too -- it's basically (y, i know i'm generalizing) a fork/provides same (type of at least; does differ in some) functionality as CDBI (note that the docs say that the "object API is inspired by Class::DBI")
      Great, thank you very much for that link! It contains useful information about pros and cons of using SQL statements vs. using an OO wraper (such as Class::DBI).
Re: Class::DBI vs. DBIx::Class
by CountZero (Bishop) on Jun 25, 2006 at 12:56 UTC
    I have used both Class::DBI and DBIx::Class within the framework of Catalyst. As DBIx::Class has a more active and lively community, I prefer it, even when its API is not yet fully settled (it hasn't yet reached version 1 - or one could say it is version "2" of Class::DBI).

    For smaller non-Catalyst programs I prefer to directly use DBI itself as setting up the OO-framework takes some time.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      Thank you for this useful insight! An active community is worth much, so I decided to use DBIx::Class for now. Setting it up and using it turned out to be only slightly more difficult (see my stumbling above) than for Class::DBI.
        One more thing on Class::DBI (I don't know if it exists for DBIx::Class) : Class::DBI::Loader. This module waits for database access parameters and give instant access to all database table as Class::DBI objects. More, relation between all this objects (by foreign keys) are also available. A great lesson of lazyness leading to very small code (using Template-Toolkit for the view part in web development).
Re: Class::DBI vs. DBIx::Class
by srdst13 (Pilgrim) on Jun 26, 2006 at 16:51 UTC
    While the original question was about CDBI versus DBIC, I think it is probably worth mentioning Rose::DB::Object. It has many of the features of CDBI and DBIC, is faster for many tasks, and also has an active user community (and author). Most importantly for me, it has absolutely FANTASTIC documentation!

    Sean
      Most importantly for me, it has absolutely FANTASTIC documentation

      Disagree very strongly. But supposedly the author is aware of the issues and the "tutorial" may be rewritten some day, so I'm reluctant to throw any specific rocks.

        I've gotten requests for a "quick-start" guide, which I plan to add. I also plan to add a FAQ and/or a "how-to" guide for common questions and tasks.

        My baseline for any release is 100% complete reference documentation, meaning every method and all its options are documented. For people who learn best from reference-style documentation, this is extremely helpful. Worst case, someone can post to the mailing list and I can point out which part of the documentation to read.

        But with a very big, feature-rich module, it's hard for some people to find a "way in," so to speak. The existing tutorial was my first step towards helping with that, providing a narrative-style exploration of the major features as well as examples of best practices. I think the quick-start guide will be next.

        If anyone has any more suggestions, just email me or post to the mailing list

Re: Class::DBI vs. DBIx::Class
by arthas (Hermit) on Jun 28, 2006 at 12:59 UTC
    I had been a user of Class::DBI for some time, but when I tried DBIx::Class I migrated almost instantly. The fact that it is ResultSet-oriented is very handy, and also the ability to specify search conditions using SQL::Abstract is awesome (there's also a plugin for Class::DBI for that, however). Even more improtantly, the DBIx::Class community is active and growing, while the Class::DBI community is becoming a bit still. Also, the author of Class::DBI declares he's not in the community of his module, which doesn't seem so good to me... I still have to try Rose::DB::Object, regarding which everybody seems to talk well! Michele.
      I'm with arthas. DBIx::Class is very handy. Check out the docs---start with DBIx::Class::Manual::DocMap and read all the manuals listed. DBIx::Class::Manual::Cookbook will give you some more ideas. Also, read DBIx::Class::Manual::Troubleshooting.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://557402]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (5)
As of 2024-04-19 22:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found