2

I have the following data model:

enter image description here

I am writing a WCF service that needs to support adding new Report:

 public bool CreateNewReport(Report report)
    {
        MyEntities context = new MyEntities();
        context.AddToReports(Report);
        context.SaveChanges();
    }

So my method gets a report object that was made on the client and adds it to the database throught the data context. (all of the members are included in the DataContract)

My question is regarding navigation properties.

  1. Do the client also needs to create a user object and put it in the new report object before sending it ?
  2. What is the best way to approach this ? one way i think of is adding a UserId field in the ReportEntity
  3. when a new report is inserted, how do i update the UserEntity Report nav property that with the new Report ?

Thanks.

Michael
  • 22,196
  • 33
  • 132
  • 187
  • 1
    One side note: Always use entity context with using: `using (var ctx = new MyEntities()) { ... }`. This will call `Dispose` at the end of the using block which will release all used resources... – Rico Suter Apr 06 '12 at 10:35
  • @RicoSuter good point, thanks – Michael Apr 06 '12 at 10:47

1 Answers1

1

If you import your database, generate navigation properties (the properties in your picture) AND foreign id properties (then you have for example an User and UserID property in your report class). This way you can set the UserID in your client and send it to the server and add it with AddToReports... If you send the whole user object you have to attach it to the entity context otherwise the user will be created once again...

Attach the referenced user: (but it's better to send the user only by id)

public bool CreateNewReport(Report report)
{
    using (MyEntities context = new MyEntities())
    {
         context.AddToReports(Report);
         context.Users.Attach(report.User);
         context.SaveChanges();
    }
}

To change the report of a user:

public bool ChangeUserToNewReport(int userid, Report newReport)
{
    using (MyEntities context = new MyEntities())
    {
         var user = context.Users.Single(u => u.ID = userid);
         user.Report = newReport;
         context.SaveChanges();
    }
}

For an existing report:

public bool ChangeUserReport(int userid, Report existingReport)
{
    using (MyEntities context = new MyEntities())
    {
         context.Reports.Attach(existingReport);
         var user = context.Users.Single(u => u.ID = userid);
         user.Report = existingReport;
         context.SaveChanges();
    }
}

This is a sample how your model should look like. Double click on the association line to open the dialog. You can see that the Person and PersonID properties are the same. If you create your model like this, VS should generate the correct SQL. enter image description here

Rico Suter
  • 11,548
  • 6
  • 67
  • 93
  • Thank you, would you mind showing me how i would do it if i had UserID foreign id property in the report class as you suggested ? how would i make the Users table aware of the new Report ? – Michael Apr 06 '12 at 11:01
  • I don't understand your question. I assume you already have a foreign key `ReportID` in your database from which the `Report` navigation property is derived? With the `ReportID` and `Report` properties you only have two ways to access this foreign key (the `Report` property supports lazy loading etc...) – Rico Suter Apr 06 '12 at 11:04
  • sorry, as i am new with EF and my DB knowledge is not so great. from what i understand you have suggested that i should add another property to `ReportEntity` that named `UserId` (not the PK on the `UserEntity`) and update it when i create a new report. This way i wouldnt need to create a User object and encapsulate it within Report when i send it from the client. correct ? besides that i have a One to Many relation with Report and Users – Michael Apr 06 '12 at 11:10
  • Yes, correct. You only have to set `UserId` not a whole reference in `User`. Are you generating the model from your database? The `User` property is not really in your database its only a "virtual" property which uses your foreign key (i think an integer, i assume it is called `UserId`) to pull the referenced object from the users table and create a .net object. – Rico Suter Apr 06 '12 at 11:13
  • 1
    I am actually creating the DB from the model with `Generate database from model` tool in VS (which creates a sql file to run on the db). So i should add a `UserId` property to the `ReportEntity` model and pass it along with Report from the client. then i use `context.AddToReports(Report);` okay, and then i search the user in the `UserEntity` according to the `UserId` but do i also need to update it there somehow ? – Michael Apr 06 '12 at 11:27
  • Can you post the SQL file which is generated? (only with the User navigation property) – Rico Suter Apr 06 '12 at 11:32
  • If you design like in my screenshot it should generate the correct SQL and you can choose whether to use the `User` or `UserID` property... – Rico Suter Apr 06 '12 at 11:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9777/discussion-between-michael-and-rico-suter) – Michael Apr 06 '12 at 11:46