none
one to one relationship entity framwork RRS feed

  • Question

  • I need to bind one to one relationship with entity framework and i dont know how.

    My model schema is:

     Model

    This is how i bind it with winforms by draging Person Details:

    Bind

    And the code looks like this:

    Imports Model
    
    Public Class Form1
    
        Dim context As HREntities
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            context = New HREntities
    
            Try
                Me.PersonBindingSource.DataSource = context.People.ToList
            Catch ex As Exception
    
            End Try
        End Sub
    
        Private Sub PersonBindingNavigatorSaveItem_Click(sender As System.Object, e As System.EventArgs)
            Me.Validate()
            Try
                Me.PersonBindingSource.EndEdit()
    
                For Each item As Person In PersonBindingSource.List
                    If item.EntityState = Data.EntityState.Detached Or item.EntityState = Data.EntityState.Added Then
                        context.People.AddObject(item)
                    End If
                Next
    
                context.SaveChanges()
                context.AcceptAllChanges()
                MessageBox.Show("Your data has been saved to the database", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End Sub
    End Class
    
    This saves all the data to the database, but when i restart the application i dont see the customer & employee details and even if i make some changes to those 2 entities it doesnt save

    Monday, March 12, 2012 12:39 PM

Answers

  • Hi Jonnyali;

    To your statement, "The data is saved to the database because every time a create a new person i instantiate the employee and customer class", The code you posted, below, was commented out in the project you posted. This is not the place to do this.

    Partial Public Class Person
        Sub New()
            Me.Employee = New Employee
            Me.Customer = New Customer
        End Sub
    End Class

    The reasoning is this when you start the project your form load executes the following code.

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    
        context = New HREntities
    
        Try
            Me.PersonBindingSource.DataSource = context.People.ToList
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        
    End Sub


    When the query is executed you get the exception "Multiplicity constraint violated. The role 'Employee' of the relationship 'HRModel.FK_Employee_inherits_Person' has multiplicity 1 or 0..1." and the most likely reason is that your Partial Person class gets executed before each object ofmaterializedet meterialized and most likely fails because Employee and Customer can have at most one object assigned to it which is done in the creation of Personresultse query resolts makes that two. This is the reason why if you comment that Partial class out the error does not happen there and why my suggestion worked.

    To your question, "How should i bind Person with its details in the current form?", The binding that you have seems to be correct because all I did was to make the modification I stated in my post and all seemed to be well.



    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".


    Friday, March 16, 2012 2:54 PM

All replies

  • Hi Jonnyali;

    It sounds like you are using SQL CE or SQL Express which uses local database files in your project. The database files get copied to your bin directory depending on the property Copy to Output Directory. What may be happening is that each time you re-start the program it over writes the one you made the modifications to in the bin directory. Read this article to see if this is your issue.

    How to: Manage Local Data Files in Your Project

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Monday, March 12, 2012 3:31 PM
  • Hi Fernando,

    This is not the issue i'm facing with. If i reopen the detail form without restarting the app. it wont work. I thing there is something i'm doing wrong by reading and binding the data.

    When i say context.People.Include("Employee").ToList i'l get the following error msg: Multiplicity constraint violated. The role 'Employee' of the relationship 'HRModel.FK_Employee_inherits_Person' has multiplicity 1 or 0..1.

    I also have a partial class for person and initialize it when ever a user adds a new record

    Sub New()
            Me.Employee = New Employee
            Me.Customer = New Customer
    End Sub
    This works fine and adds data to other tables but reading it and edit it doesnt work.
    Tuesday, March 13, 2012 7:54 AM
  • Hi Jonnyali;

    What version of EF are you using, 4.0, 4.1, 4.2 or 4.3?
    What are you using Database First, Model First or Code First?
    If you are using Code First can you post the class models and configuration of the classes.

    In the diagram you have posted it shows the relationships as being 1 Person to zero or one Customer and zero or one Employee, meaning you can have a person with nothing defined as a Customer or Employee.

    If you have a test project that you can zip up and post to Windows Live Skydrive so that we can run it and see where the issue is that would help.

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Tuesday, March 13, 2012 1:33 PM
  •  

    Did you create the associations between Person and Customer and Person and Employee manually in the EDMX designer?

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Tuesday, March 13, 2012 3:55 PM
  •  

    If you have a sample database file that you can zip up so that I can try and reproduce the problem here would be a help.

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Tuesday, March 13, 2012 4:13 PM
  • I've first started creating this project using model first and generated the database from model.

    The table names created on the database was Person_Employee Person_Customer which i don't like, so i decided to start the project with database first.

    This gives me clean names Person, Employee & Customer.

    You can generate the database from the model or you can copy this code:

    USE [HR];
    GO
    IF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]');
    GO
    
    -- --------------------------------------------------
    -- Dropping existing FOREIGN KEY constraints
    -- --------------------------------------------------
    
    IF OBJECT_ID(N'[dbo].[FK_Customer_inherits_Person]', 'F') IS NOT NULL
        ALTER TABLE [dbo].[Customer] DROP CONSTRAINT [FK_Customer_inherits_Person];
    GO
    IF OBJECT_ID(N'[dbo].[FK_Employee_inherits_Person]', 'F') IS NOT NULL
        ALTER TABLE [dbo].[Employee] DROP CONSTRAINT [FK_Employee_inherits_Person];
    GO
    
    -- --------------------------------------------------
    -- Dropping existing tables
    -- --------------------------------------------------
    
    IF OBJECT_ID(N'[dbo].[Customer]', 'U') IS NOT NULL
        DROP TABLE [dbo].[Customer];
    GO
    IF OBJECT_ID(N'[dbo].[Employee]', 'U') IS NOT NULL
        DROP TABLE [dbo].[Employee];
    GO
    IF OBJECT_ID(N'[dbo].[People]', 'U') IS NOT NULL
        DROP TABLE [dbo].[People];
    GO
    
    -- --------------------------------------------------
    -- Creating all tables
    -- --------------------------------------------------
    
    -- Creating table 'Customers'
    CREATE TABLE [dbo].[Customers] (
        [Code] nvarchar(max)  NOT NULL,
        [Discount] decimal(18,2)  NOT NULL,
        [Id] int  NOT NULL
    );
    GO
    
    -- Creating table 'Employees'
    CREATE TABLE [dbo].[Employees] (
        [HireDate] datetime  NOT NULL,
        [Position] nvarchar(max)  NOT NULL,
        [Id] int  NOT NULL
    );
    GO
    
    -- Creating table 'People'
    CREATE TABLE [dbo].[People] (
        [Id] int IDENTITY(1,1) NOT NULL,
        [FirstName] nvarchar(max)  NOT NULL,
        [LastName] nvarchar(max)  NOT NULL
    );
    GO
    
    -- --------------------------------------------------
    -- Creating all PRIMARY KEY constraints
    -- --------------------------------------------------
    
    -- Creating primary key on [Id] in table 'Customers'
    ALTER TABLE [dbo].[Customers]
    ADD CONSTRAINT [PK_Customers]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- Creating primary key on [Id] in table 'Employees'
    ALTER TABLE [dbo].[Employees]
    ADD CONSTRAINT [PK_Employees]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- Creating primary key on [Id] in table 'People'
    ALTER TABLE [dbo].[People]
    ADD CONSTRAINT [PK_People]
        PRIMARY KEY CLUSTERED ([Id] ASC);
    GO
    
    -- --------------------------------------------------
    -- Creating all FOREIGN KEY constraints
    -- --------------------------------------------------
    
    -- Creating foreign key on [Id] in table 'Customers'
    ALTER TABLE [dbo].[Customers]
    ADD CONSTRAINT [FK_Customer_inherits_Person]
        FOREIGN KEY ([Id])
        REFERENCES [dbo].[People]
            ([Id])
        ON DELETE NO ACTION ON UPDATE NO ACTION;
    GO
    
    -- Creating foreign key on [Id] in table 'Employees'
    ALTER TABLE [dbo].[Employees]
    ADD CONSTRAINT [FK_Employee_inherits_Person]
        FOREIGN KEY ([Id])
        REFERENCES [dbo].[People]
            ([Id])
        ON DELETE NO ACTION ON UPDATE NO ACTION;
    GO
    
    -- --------------------------------------------------
    -- Script has ended
    -- --------------------------------------------------

    Thx in advance!
    Wednesday, March 14, 2012 7:10 AM
  • Hi Jonnyali;

    To the question, "This saves all the data to the database, but when i restart the application i dont see the customer & employee details and even if i make some changes to those 2 entities it doesnt save", the issue with making changes to already existing data not being saved is due to the fact that the binding source control makes the changes to the underlying data but never issues a context.SaveChanges() to the database. To persist any database modification you will need to execute a context.SaveChanges() before leaving the application.

    On the issue of the Customer and Employee data is not being persisted it is because you need to create an object of Employee or Customer and attach it to the Person object once that is done then the binding source will keep the object in sync. Remember that both the Employee and Customer object can have none or one of the object so it is not automatically created.

    For example I placed a check box on the form clicked the Add Item button in the BindingNavigator filled in the text boxes checked the check box for an employee and did not check for customer and clicked the save button on the BindingNavigator with the following code snippet in it.

    If CheckBox1.Checked = True Then
        Dim emp = New Employee
        emp.HireDate = HireDateDateTimePicker.Value
        emp.Position = PositionTextBox.Text
        CType(PersonBindingSource.Current, Person).Employee = emp
    Else
        Dim cust As New Customer
        cust.Code = CodeTextBox.Text
        cust.Discount = CType(DiscountTextBox.Text, Decimal)
        CType(PersonBindingSource.Current, Person).Customer = cust
    End If

      


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Thursday, March 15, 2012 5:31 PM
  • Hi Fernando,

    The data is saved to the database because every time a create a new person i instantiate the employee and customer class

    Partial Public Class Person
        Sub New()
            Me.Employee = New Employee
            Me.Customer = New Customer
        End Sub
    End Class

    Navigating through gives me nothing but Person data. Here is my load event

        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            context = New HREntities
            Try
    
                Me.PersonBindingSource.DataSource = context.People.ToList
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End Sub

    I can't use Include here because it's one to one relationship.

    How should i bind Person with its details in the current form?


    • Edited by Jonnyali Friday, March 16, 2012 8:21 AM
    Friday, March 16, 2012 8:11 AM
  • Hi Jonnyali;

    To your statement, "The data is saved to the database because every time a create a new person i instantiate the employee and customer class", The code you posted, below, was commented out in the project you posted. This is not the place to do this.

    Partial Public Class Person
        Sub New()
            Me.Employee = New Employee
            Me.Customer = New Customer
        End Sub
    End Class

    The reasoning is this when you start the project your form load executes the following code.

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    
        context = New HREntities
    
        Try
            Me.PersonBindingSource.DataSource = context.People.ToList
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        
    End Sub


    When the query is executed you get the exception "Multiplicity constraint violated. The role 'Employee' of the relationship 'HRModel.FK_Employee_inherits_Person' has multiplicity 1 or 0..1." and the most likely reason is that your Partial Person class gets executed before each object ofmaterializedet meterialized and most likely fails because Employee and Customer can have at most one object assigned to it which is done in the creation of Personresultse query resolts makes that two. This is the reason why if you comment that Partial class out the error does not happen there and why my suggestion worked.

    To your question, "How should i bind Person with its details in the current form?", The binding that you have seems to be correct because all I did was to make the modification I stated in my post and all seemed to be well.



    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".


    Friday, March 16, 2012 2:54 PM