Entity Wrapper - Custom

2019-03-04 07:35发布

问题:

I would like find a workaround to accomplish a simple solution in order to automatize certain operation through EF. What I need it's takeover during saving and retrieving process to modifying query result, but this class will be able to make that work for any type entities.

Example: I have a MyTestDb. So in my C# project I create a new entity model (MyTEstDbModel.edmx), with relative POCO class generation. Well, a point of interest could be implementing a new custom class like following:

class Example
{
   private ObjectContext _context;
   private Example(ObjectContext obj) { _context = obj; }

   public void Store(ObjectSet<???generic???> os)
   {
       // problem here: I dont't know the type contained in ObjectSet
       // but if I Knew its type, I could make a work like this:
       // -> foreach every instance in objectSet to check if exist some property 
       // via reflection, if i found them, then I set always the same values.
       // Why this? Because all my db contains some common filed 
       // like (createdByUser, TimeToUpdate, and so on..), so it wold be boring 
       // setting all those fileds from any point of program.
   }

public void Retrive(ObjectSet<???generic???> os)
{
   // here problem too: all my queries will be filtered by one or more value
   //  fileds, but I cannot use lambaExpression cos I don't Know the type 
   // contained in objectSet<..>
}
//....

finally, by any point of program, the code should appear like following:

Example obj = new Example(myEntityContext); //-> global

var result = myEntityContext.ObjectSetTyped.Where(..lambaExpression..condition)
result.someProperty = "...";
obj.Store(result); // store method will fill all other boring filed automatically.

Can anyone give me some tips, help, suggestion about my issue?

Thanks in advance...

Update

Now, just only another problem. I'd to filter my ObjectSet through retrieve method like following:

public void Retrieve<TEntity>(IQueryable<TEntity> ooo) where TEntity : IC
{
    ooo = ooo.Where(p => p.Filed == "MyDefaultValue");
}

But, from external method, not objectSet result is affect by my filter. How so..?

MyEntities ent = new...
MyWrapper wrap = new MyWrapper();
wrap.Retrieve(ent.Users);

//problem here -> users objectSet is always the same..

回答1:

Define interfaces which will allow you to do this. For example:

public interface IEntity
{
  DateTime CreatedAt { get; set; }
  string CreatedBy { get; set; }
}

You need to "implement" this interface in your entities. You can for example either modify T4 template generating entities or implement it in partial class. Both properties must be already defined in the model so the implementation is only declarative:

public partial class MyEntity : IEntity // That's all
{ }

Now you can define Store like:

public void Store<TEntity>(TEntity entity) where TEntity : IEntity
{
  ...
}

Same can be done with query but you can for example define custom extension method:

public static IQueryable<TEntity> GetUserEntities(this IQueryable<TEntity> query, string user) 
    where TEntity : IEntity 
{
   return query.Where(e => e.CreatedBy == user);
}

You will simply define your query like:

var result = myEntityContext.MyEntities.GetUserEntities("someName");

Other approach is defining simply GetQuery on your custom context:

public IQueryable<T> GetQuery<T>() where T : IEntity
{
    var query = GetObjectSetSomehow;
    return query.ApplyGlobalConditions(); // Just another extension with your conditions
}

I'm not a big fan of the repository pattern but generally what you are trying to do is close to generic repository so check for example this post. It is just some example which can be further extended.



回答2:

yeah, I just want a generic approach, likewise I realized with dataset and datatable.. but it seems impossible to achieve..

..ehmm..however, let me show yuo following code snippet, dynamic keyword looks like something to hopeful.... maybe I'm colse to solution..?

    public ObjectSet<dynamic> Retrieve(string entity, string context)
    {
        Type myObjectContextType = Type.GetType(context);            
        ConstructorInfo cs = myObjectContextType .GetConstructor(new Type[] { });
        dynamic myObjContext = cs.Invoke(new object[] { });

        Type t = Type.GetType(entity);
        ConstructorInfo xi = t.GetConstructor(new Type[] { });
        dynamic UserEntity = xi.Invoke(new object[] { });

        !problem here!
        ObjectSet<?????> os = myObjContext.UserEntity.Where(...) 

        return ...           

    }

I'm very surprised..EF is a great instruments to develope more efficiently ways but too little "generalizalbe"