Wrong results for 1:1 reference

7 posts, 1 answers
  1. Igor
    Igor avatar
    145 posts
    Member since:
    Jan 2011

    Posted 22 Jul 2012 Link to this post

    Hi,
    i am using Telerik OpenAccess ORM 2012.2.607.1
    Creating the empty domain model with MySQL backend in Visual Studio 2010 SP1 using Telerik ORM Designer (Create Domain Model -> Empty model, etc...).

    Identity mechanism: HighLow
    I've created User table and UserDetails table with 1:1 association (User can have 1 (One) instance of UserDetails), bind by  User.Id <---> UserDetails.Id.
    All tables are mapped (using the "Map to table..." command).
    The following script is being executed against DB to create the tables and constraints:

    -- ConsoleApplication1.UserDetails
    CREATE TABLE `user_details` (
        `id` integer NOT NULL,                  -- _id
        `email` varchar(255) NULL,              -- _email
        CONSTRAINT `pk_user_details` PRIMARY KEY (`id`)
    ) ENGINE = InnoDB;
     
    -- ConsoleApplication1.User
    CREATE TABLE `usr` (
        `user_name` varchar(255) NULL,          -- _userName
        `id` integer NOT NULL,                  -- _id
        CONSTRAINT `pk_usr` PRIMARY KEY (`id`)
    ) ENGINE = InnoDB;
     
    -- OpenAccessRuntime.Relational.sql.HighLowRelationalKeyGenerator
    CREATE TABLE `voa_keygen` (
        `table_name` VARCHAR(64) NOT NULL,
        `last_used_id` INTEGER NOT NULL,
        CONSTRAINT `pk_voa_keygen` PRIMARY KEY (`table_name`)
    ) ENGINE = InnoDB;
     
    ALTER TABLE `user_details` ADD CONSTRAINT `ref_user_details_usr` FOREIGN KEY `ref_user_details_usr` (`id`) REFERENCES `usr` (`id`);

    The following code is being executed after that:

    EntitiesModel model = new EntitiesModel("Server=192.168.1.55;Database=test;Uid=user;Pwd=pass;");
     
    model.Add(new User { UserName = "test 1" });
    model.Add(new User { UserName = "test 2", UserDetails = new UserDetails { Email = "test2@email.tst" } });
     
    model.SaveChanges();

    So in mySQL database i got next data (represented as CSV):
    Table "Usr"
    user_name,id
    "test 1",1
    "test 2",2

    Table "UserDetails"
    id,email
    1,"test2@email.tst"

    When selecting the data with the C# code below:

    EntitiesModel model = new EntitiesModel("Server=192.168.1.55;Database=test;Uid=user;Pwd=pass;");
    User user = model.GetAll<User>().FirstOrDefault(x => x.UserName == "test 2");
    UserDetails details = user.UserDetails; // ?? <--- details == null... why ??

    i've got the user object instance created well, but the UserDetails property is equals to null.
    In other hand, when i selecting the first record (id == 1) like that:
    User user = model.GetAll<User>().FirstOrDefault(x => x.UserName == "test 1");
    UserDetails details = user.UserDetails; // ?? <--- details are not null here

    I've got details record, but it is not the expected behavior.
    It's clear for me that there is an issue with Identity, so i've tried to put the Identity by hand (detials.Id = 2) when creating the details, but it does not work (It will put the value "1" to the Details table instead).

    Could you please direct me to the right way to accomplish my goal? Thanks!
    p.s. Attaching my project : http://www.4shared.com/zip/UGw6IzNa/ConsoleApplication1.html 
  2. Igor
    Igor avatar
    145 posts
    Member since:
    Jan 2011

    Posted 24 Jul 2012 Link to this post

    Guys, please help ! :(
  3. DevCraft banner
  4. Zoran
    Admin
    Zoran avatar
    534 posts

    Posted 25 Jul 2012 Link to this post

    Hello Igor,

     Thanks for reporting this issue to us. We did confirm a bug with the workflow you currently have and it is only related to objects that use the HighLow key generator. There is an easy workaround for your case though. The problem is related to the fact that the parent object (User) is not added to the context when the reference is being assigned. That said, here is a workaround:

    EntitiesModel model = new EntitiesModel("Server=192.168.1.55;Database=test;Uid=user;Pwd=pass;");
     
    model.Add(new User { UserName = "test 1" });
     
    User user = new User { UserName = "test 2" };
     
    UserDetails detail = new UserDetails { Email = "test2@email.tst" };

    model.Add(user); 

    user.UserDetails = detail;
     
    model.SaveChanges();
     
    User user2 = model.GetAll<User>().FirstOrDefault(x => x.UserName == "test 2");
    UserDetails details = user2.UserDetails; // the details are now synchronized correctly.

    The main point is that the user object is added to the context, before the UserDetails is assigned unlike the object-initializer assignment from your code.

    Once again, thanks for helping us locate this bug, your Telerik points have been updated.Greetings,
    Zoran
    the Telerik team
    OpenAccess ORM Q2'12 Now Available! Get your hands on all the new stuff.
  5. Igor
    Igor avatar
    145 posts
    Member since:
    Jan 2011

    Posted 25 Jul 2012 Link to this post

    Zoran, thanks for answering i will try the workaround shortly
  6. Andrey
    Andrey avatar
    5 posts
    Member since:
    Jul 2012

    Posted 25 Jul 2012 Link to this post

    Unfortunately it does not work. The problem persisted.
  7. Answer
    Andrey
    Andrey avatar
    5 posts
    Member since:
    Jul 2012

    Posted 26 Jul 2012 Link to this post

    Here is a workaround:

    Create Domain Class
    User
    {
        ID: Int32;
        UserName: String;
        UserDetails: UserDetails; //allow null
    }

    and
    UserDetails
    {
        ID: Int32;
        Email: String;
        User: User; //allow null
    }

    The following code works correctly:
    User u1 = new User { UserName = "test 1", UserDetails = null };
    model.Add(u1);
     
    User u2 = new User { UserName = "test 2", UserDetails = new UserDetails { Email = "email 2" } };
    u2.UserDetails.User = u2;
    model.Add(u2);
     
    User u3 = new User { UserName = "test 3", UserDetails = new UserDetails { Email = "email 3" } };
    u3.UserDetails.User = u3;
    model.Add(u3);
     
     
     
    UserDetails ud1 = new UserDetails { Email = "email 1", User = null };
    model.Add(ud1);
     
    UserDetails ud4 = new UserDetails { Email = "email 4", User = new User { UserName = "user4" } };
    ud4.User.UserDetails = ud4;
    model.Add(ud4);
     
     
    model.SaveChanges();
  8. Igor
    Igor avatar
    145 posts
    Member since:
    Jan 2011

    Posted 26 Jul 2012 Link to this post

    i confirm that workaround mentioned by Andrey works for me.
    Will be waiting for Telerik to fix the bug
Back to Top
DevCraft banner