1

I have 2 entities, let's say A and B. Relation between them is many-to-many so I have another entity, let's say C.

Columns for table A:
-Id (PK) -> Type int generated by database
-PropertyA1
-PropertyA2
-PropertyA3

Columns for table B:
-Id (PK) -> Type int generated by database
-Description

Columns for table C (For this table I am not sure if it is better to add an extra column Id generated by database as previous tables):
-IdA (PK and also foreign key to entity A)
-IdB (PK and also foreign key to entity B)

Table B has fixed values that are inserted on seed method (overrided). Its entries are like below:
Id Description
1 "Some description 1"
2 "Some description 2"
3 "Some description 3"

From a form, user introduces the information related to table A (propertyA1,...,propeprtyA3) and then click on a button to save the data to the database.

Once user clicks on button's form to save data into database, first I do the following:

   A a = new A(){ PropertyA1=something_1,
                  PropertyA2=something_2,
                  PropertyA3=something_3 };

   context.A.Add(a);
   context.SaveChanges();

then as after saving changes to database I have the Id generated by database (I have not id before saving to database), that is, a.Id, now I can proceed to add an entry to table C by doing:

  B b = this.ObtainAppropriateB();
  C c = new C(){ IdA = a.Id,
                 IdB = b.Id };

  context.C.Add(c);
  context.SaveChanges();

My problem is:
1) I cannot know a.Id previous to do context.SaveChanges after context.A.Add(a) because it is generated by database.
2) If context.SaveChanges fails after context.C.Add(c), how can I rollback as well previous work done?:
context.A.Add(a);
context.SaveChanges();

I cannot do the following because I have not a.Id previous to do SaveChanges:

   A a = new A(){ PropertyA1=something_1,
                  PropertyA2=something_2,
                  PropertyA3=something_3 };

   context.A.Add(a);
   B b = this.ObtainAppropriateB();
   C c = new C(){ IdA = a.Id,
                  IdB = b.Id };

   context.C.Add(c);

   context.SaveChanges(); <--- I call it once to persist changes to database

How to solve this?

4

2 回答 2

5

This is not the way you work with a many-to-many relationship with Entity Framework.

First, you should not have a C entity in your model but instead collection properties on entity A and B:

public class A
{
    public int AId { get; set; }
    public int PropertyA1 { get; set; }
    public string PropertyA2 { get; set; }
    public DateTime PropertyA3 { get; set; }

    public ICollection<B> Bs { get; set; }
}

public class B
{
    public int BId { get; set; }

    // ...

    public ICollection<A> As { get; set; }
}

From the collections EF is able to figure out that the relationship is many-to-many and that a link table (C) is needed. You can define the mapping details with Fluent API.

Second, once you have the navigation collections you don't need to care about the Ids. You just build an object graph with the necessary relationships and save it to the database:

A a = new A() { PropertyA1 = something_1,
                PropertyA2 = something_2,
                PropertyA3 = something_3 };
a.Bs = new List<B>();

B b = this.ObtainAppropriateB(); // must use same context instance

a.Bs.Add(b);

context.A.Add(a);
context.SaveChanges();

It will create a new A and insert the relationship row between a and b into the link table.

于 2013-05-18T16:55:58.800 回答
1

I think the problem is that you think in database terms instead of model terms. You should forget about table C as this table will be generated by the database. You should have in class A a collection of B and in class B a collection of A. Then specify the many-to-many relationship. If you add a B to A, and save your context, the appropiate data will be added to the table C.

于 2013-05-18T16:51:33.267 回答