开发者

Retrieving an Entity Object by name - LINQ to Entities, EF 4.0

I have a number of entity objects that are structurally the same but the naming convention is different e.g Products1, Products2, Products3 (this is part of the legacy db schema and I can't do much about this).

These classes are of different types as far as CLR is concerned and unfortunately since the design code is auto-generated I can't slap an interface on these guys to show commonality. So, my question is: Is there a way to retrieve the entity object by name?

I'd basically like to av开发者_如何学编程oid switch/case business when applying essentially the same logic to these objects.


You could build an Expression tree to query for the object or objects in question:

public T GetSingleObject<T>(int someValue) {
    MyEntities db = new MyEntities();
    var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));

    var param = Expression.Parameter(typeof(T));

    var lambda = Expression.Lambda<Func<T, bool>>(
        Expression.Equal(
            Expression.Property(param, "WhateverPropertyYourComparing"),
            Expression.Constant(someValue)),
        param);

    return result.SingleOrDefault(lambda);
}

Or if you want a collection of objects

public IEnumerable<T> GetResultCollection<T>(int someValue) {
    MyEntities db = new MyEntities();
    var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));

    var param = Expression.Parameter(typeof(T));

    var lambda = Expression.Lambda<Func<T, bool>>(
        Expression.Equal(
            Expression.Property(param, "WhateverPropertyYourComparing"),
            Expression.Constant(someValue)),
        param);

    return result.Where(lambda);
}

Of course if your desired query is very long, this can get out of hand, and you should consider adding in the necessary interface using partial classes, as Justin Morgan suggested.

Note that this method assumes that your ObjectSet collection is the same name as your object, plus an "s", ie, "Invoice" to "Invoices". If that's not the case, ie, "Person" to "People", then you could use System.Data.Entity.Design.PluralizationServices.PluralizationService to get the proper name


Since the EF4 classes are partial classes you can actually extend them and make them implement an interface of your choice, all in a separate file.

An alternative to that would be using dynamic - just instantiate the entity based on it's type.

dynamic myEntity= Activator.CreateInstance(Type.GetType("EntityTypeHere")));
myEntity.CommonProperty = "Foo";

The big disadvantage here is that you lose all type safety at compile time - any problem you will only discover at runtime, also it's slower than the statically typed approach.


Depending on how many classes we're talking about, and how flexible you need to be, interfaces might not be out of the question. I've done something similar using generics:

//WARNING: Partially-remembered code ahead...
interface IDuckEntity
{
    int FeatherCount { get; set; }
}

public partial class Products1 : IDuckEntity { }
public partial class Products2 : IDuckEntity { }
public partial class Products3 : IDuckEntity { }

//in some other class:
void DoStuff<T>(T entity) where T : EntityObject, IDuckEntity
{
     entity.FeatherCount = 500;
}

So basically, you set up a separate file where you put the interface and a bunch of those little partial class declarations. Then you'll have access to the common structure. I don't know what your exact situation is, but this worked like a charm for me.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜