How to DML data in one simple function under EF?

Discussion of open issues, suggestions and bugs regarding Entity Framework support in ADO.NET Data providers
Post Reply
Lyu_KingT
Posts: 7
Joined: Thu 21 Oct 2010 06:08

How to DML data in one simple function under EF?

Post by Lyu_KingT » Tue 30 Nov 2010 08:02

0. i created a model from Oracle, and successfully DML (insert, update, delete) data with EF;
1. however, for each entity of this model, i have to write a special function to DML it (so if i have 10 entities, i have to write a similar code for 10 times), like

Code: Select all

static DmlEntityA{
      void Insert(entityA);
      void Update(entiyA);
      void Delete(entityA);
}

static DmlEntityB{
      void Insert(entityB);
      void Update(entiyB);
      void Delete(entityB);
}

static DmlEntityC{
      void Insert(entityC);
      void Update(entiyC);
      void Delete(entityC);
}

// ...
a more specific code was attached below.

2. is there any generic way to do such things?

thx.

Code: Select all

        private static bool PreserveChanges(MyModel.Clinic.MedRoute entity, DML dmlType)
        {
            using (var tx = new TransactionScope())
            {
                try
                {
                    using (var ctx = new MyModel.Clinic.ClinicEntities())
                    {
                        switch (dml)
                        {
                            case DML.Insert:
                                ctx.AddToClinicObjects(entity);
                                break;
                            case DML.Update:                              
                                if (null != entity)
                                {
                                    ctx.AttachTo("ClinicObjects", entity);
                                    ctx.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified);
                                }
                                break;
                            case DML.Delete:
                                var oj2 = ctx.ClinicObjects.Where(x => x.Id == entity.Id).FirstOrDefault();
                                if (null != oj2)
                                {
                                    ctx.DeleteObject(oj2);
                                }
                                break;
                            default:
                                break;
                        }

                        ctx.SaveChanges();
                    }
                    

                    tx.Complete();
                    return true;
                }
                catch (System.Data.UpdateException ex)
                {
                   // write error to log file
                    LogException(ex);
                    return false;
                }
            }
        }

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Tue 30 Nov 2010 13:14

I'd recommend you to modify the code generation template to create these methods for each EntityType.
Add a method like the following:

Code: Select all

  private void GenerateDML(EntityClass cls) {
#>        private static bool PreserveChanges( entity, DML dmlType) 
        { 
            using (var tx = new TransactionScope()) 
            { 
                try 
                { 
                    using (var ctx = new MyModel.Clinic.ClinicEntities()) 
                    { 
                        switch (dml) 
                        { 
                            case DML.Insert: 
                                ctx.AddTos(entity); 
                                break; 
                            case DML.Update:                              
                                if (null != entity) 
                                { 
                                    ctx.AttachTo("s", entity); 
                                    ctx.ObjectStateManager.ChangeObjectState(entity, System.Data.EntityState.Modified); 
                                } 
                                break; 
                            case DML.Delete: 
                                var oj2 = ctx.s.Where(x => x.Id == entity.Id).FirstOrDefault(); 
                                if (null != oj2) 
                                { 
                                    ctx.DeleteObject(oj2); 
                                } 
                                break; 
                            default: 
                                break; 
                        } 
                        ctx.SaveChanges(); 
                    } 
                    tx.Complete(); 
                    return true; 
                } 
                catch (System.Data.UpdateException ex) 
                { 
                   // write error to log file 
                    LogException(ex); 
                    return false; 
                } 
            } 
        }
<#+
to the code snippet that is responsible for class generation. For example, after this line:

Code: Select all

} // End of class navigation properties generation 
Don't forget to add the necessary assemblies (like System.Transactions) and the methods that are used in the snippet (like LogException) mentioned above.

Lyu_KingT
Posts: 7
Joined: Thu 21 Oct 2010 06:08

Post by Lyu_KingT » Wed 01 Dec 2010 01:44

AndreyR wrote:I'd recommend you to modify the code generation template ...
Add a method like the following... to the code snippet that is responsible for class generation. For example, after this line:

Code: Select all

} // End of class navigation properties generation 
thx for your reply, the code (*.cs) was generated by the MyModel.edml (devart dotConnect for Oracle), however, i cannot to locate a code generation template (*.tt) file to add your t4 code.

so where should i do now?

best wishes

PS:
by the way, can we get entitySetName from a entity, if so, we can:

ctx.AddObject(entity.entitySetName, entity);
ctx.AttachTo(entity.entitySetName, entity);
...

however i guess it cannot be done, otherwise, the AddObject() and AttachTo() just need one parameter.

AndreyR
Devart Team
Posts: 2919
Joined: Mon 07 Jul 2008 13:16

Post by AndreyR » Wed 01 Dec 2010 14:17

1. Go to the Tools->Entity Developer->Templates... menu in Visual Studio.
2. Select the New... option and load code from the existing Entity C# template.
3. Make the desired changes.
4. Open the model and set the newly created template as an active one for code generation (you can simply double-click the model surface, go to the Generation node in the Model Settings window, and select the new template in combo box).
5. Please be aware that the most suitable way to add methods like LogException to the code is to place them in the .cs file, it is designed for code that should not be affected by code regeneration.
As for the EntitySet names, you can use the following code:

Code: Select all

string entitySetName = ws.GetItems(DataSpace.CSpace).Single().BaseEntitySets.Where(it=>it.ElementType.Name == entity.GetType().Name).Select(it=>it.Name).Single();

Post Reply