EF4 LINQ包含(字符串)硬编码字符串的替代方案?

EF4 LINQ包含(字符串)硬编码字符串的替代方案?,linq,string,entity-framework,include,entity-framework-4,Linq,String,Entity Framework,Include,Entity Framework 4,除此之外,还有其他选择吗: Organizations.Include("Assets").Where(o => o.Id == id).Single() 我想看看这样的东西: Organizations.Include(o => o.Assets).Where(o => o.Id == id).Single() #region Member Constants public partial class ContactMembers {

除此之外,还有其他选择吗:

Organizations.Include("Assets").Where(o => o.Id == id).Single()
我想看看这样的东西:

Organizations.Include(o => o.Assets).Where(o => o.Id == id).Single()
    #region Member Constants
   public partial class ContactMembers
   {
        public const string ID = "ID";
                public const string OriginalSourceID = "OriginalSourceID";
                public const string EnabledInd = "EnabledInd";
                public const string EffectiveDTM = "EffectiveDTM";
                public const string EndDTM = "EndDTM";
                public const string EnterDTM = "EnterDTM";
                public const string EnterUserID = "EnterUserID";
                public const string LastChgDTM = "LastChgDTM";
                public const string LastChgUserID = "LastChgUserID";
            }

    #endregion

为了避免实体框架1.0使用硬编码字符串“Assets”。

,我创建了一些扩展方法

public static class EntityFrameworkIncludeExtension
{
    public static ObjectQuery<T> Include<T>(this ObjectQuery<T> src, Expression<Func<T, StructuralObject>> fetch)
    {
        return src.Include(CreateFetchingStrategyDescription(fetch));
    }

    public static ObjectQuery<T> Include<T>(this ObjectQuery<T> src, Expression<Func<T, RelatedEnd>> fetch)
    {
        return src.Include(CreateFetchingStrategyDescription(fetch));
    }

    public static ObjectQuery<T> Include<T, TFectchedCollection>(this ObjectQuery<T> src, Expression<Func<T, IEnumerable<TFectchedCollection>>> fetch)
    {
        return src.Include(CreateFetchingStrategyDescription(fetch));
    }

    public static ObjectQuery<T> Include<T, FetchedChild>(this ObjectQuery<T> src, Expression<Func<T, RelatedEnd>> fetch, Expression<Func<FetchedChild, Object>> secondFetch)
        where FetchedChild : StructuralObject
    {
        return src.Include(CombineFetchingStrategies(fetch, secondFetch));
    }

    public static ObjectQuery<T> Include<T, FetchedChild>(this ObjectQuery<T> src, Expression<Func<T, RelatedEnd>> fetch, Expression<Func<FetchedChild, RelatedEnd>> secondFetch)
        where FetchedChild : StructuralObject
    {
        return src.Include(CombineFetchingStrategies(fetch, secondFetch));
    }

    public static ObjectQuery<T> Include<T, FetchedChild>(this ObjectQuery<T> src, Expression<Func<T, RelatedEnd>> fetch, Expression<Func<FetchedChild, StructuralObject>> secondFetch)
        where FetchedChild : StructuralObject
    {
        return src.Include(CombineFetchingStrategies(fetch, secondFetch));
    }

    public static ObjectQuery<T> Include<T, FetchedChild>(this ObjectQuery<T> src, Expression<Func<T, IEnumerable<FetchedChild>>> fetch, Expression<Func<FetchedChild, Object>> secondFetch)
        where FetchedChild : StructuralObject
    {
        return src.Include(CombineFetchingStrategies(fetch, secondFetch));
    }

    public static ObjectQuery<T> Include<T, FetchedChild>(this ObjectQuery<T> src, Expression<Func<T, IEnumerable<FetchedChild>>> fetch, Expression<Func<FetchedChild, RelatedEnd>> secondFetch)
        where FetchedChild : StructuralObject
    {
        return src.Include(CombineFetchingStrategies(fetch, secondFetch));
    }

    public static ObjectQuery<T> Include<T, FetchedChild>(this ObjectQuery<T> src, Expression<Func<T, IEnumerable<FetchedChild>>> fetch, Expression<Func<FetchedChild, StructuralObject>> secondFetch)
        where FetchedChild : StructuralObject
    {
        return src.Include(CombineFetchingStrategies(fetch, secondFetch));
    }

    private static String CreateFetchingStrategyDescription<TFetchEntity, TFetchResult>(
        Expression<Func<TFetchEntity, TFetchResult>> fetch)
    {
        fetch = (Expression<Func<TFetchEntity, TFetchResult>>)FixedWrappedMemberAcces.ForExpression(fetch);
        if (fetch.Parameters.Count > 1)
            throw new ArgumentException("CreateFetchingStrategyDescription support only " +
                "one parameter in a dynamic expression!");

        int dot = fetch.Body.ToString().IndexOf(".") + 1;
        return fetch.Body.ToString().Remove(0, dot);
    }

    private static String CreateFetchingStrategyDescription<T>(Expression<Func<T, Object>> fetch)
    {
        return CreateFetchingStrategyDescription<T, Object>(fetch);
    }

    private static String CombineFetchingStrategies<T, TFetchedEntity>(
                Expression<Func<T, Object>> fetch, Expression<Func<TFetchedEntity, Object>> secondFetch)
    {
        return CombineFetchingStrategies<T, Object, TFetchedEntity, Object>(fetch, secondFetch);
    }

    private static String CombineFetchingStrategies<TFetchEntity, TFetchResult, TFetchedEntity, TSecondFetchResult>(
        Expression<Func<TFetchEntity, TFetchResult>> fetch, Expression<Func<TFetchedEntity, TSecondFetchResult>> secondFetch)
    {
        return CreateFetchingStrategyDescription<TFetchEntity, TFetchResult>(fetch) + "." +
            CreateFetchingStrategyDescription<TFetchedEntity, TSecondFetchResult>(secondFetch);
    }
}

我还没有在EF4.0上测试过这一点,但我希望它能工作。

这很容易做到,使用表达式:

public static class ObjectQueryExtensions
{
    public static ObjectQuery<T> Include<T, TProperty>(this ObjectQuery<T> objectQuery, Expression<Func<T, TProperty>> selector)
    {
        MemberExpression memberExpr = selector.Body as MemberExpression;
        if (memberExpr != null)
        {
            return objectQuery.Include(memberExpr.Member.Name);
        }
        throw new ArgumentException("The expression must be a MemberExpression", "selector");
    }
}

请参阅“”。

好消息是EF4 CTP4当前支持此功能。

另一个选项是使用TT模板在类中包含内部分部类

T4代码:

<#
    region.Begin("Member Constants");
#>
   public partial class <#=code.Escape(entity)#>Members
   {
<#
    foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
    {
        bool isForeignKey = entity.NavigationProperties.Any(np=>np.GetDependentProperties().Contains(edmProperty));
        bool isDefaultValueDefinedInModel = (edmProperty.DefaultValue != null);
        bool generateAutomaticProperty = false;
        #>
        public const string <#=code.Escape(edmProperty)#> = "<#=code.Escape(edmProperty)#>";
        <#
    }
    #>
    }
    <#
    region.End();
#>
在EF 4.1中,对此有一个定义

您必须在项目中引用“EntityFramework”程序集(EF 4.1所在的位置),并使用System.Data.Entity

using System.Data.Entity; 
如果要包括嵌套实体,请按如下方式执行:

        db.Customers.Include(c => c.Orders.Select(o => o.LineItems))

不确定这是否适用于EF4.0实体(基于ObjectContext)。

另一种解决方案是使用EntitySet.name检索实体名称。
您的代码将是:

var context = new DBContext();  
context.Organizations.Include(context.Assets.EntitySet.Name).Where(o => o.Id == id).Single()

是的,我也是这样开始的,但您的缺点是,在编译时,它可能会生成运行时异常。因为你没有限制TProperty可以是什么。EF只喜欢Include中自己的属性,因为它不能将自己声明的属性映射到它的数据模型(至少在EF1.0中是这样)。这就是我包含所有重载的原因,这些重载限制表达式以提供include的编译时安全性。虽然LINQ中的所有其他表达式仍然可以生成运行时错误。同意。。。不幸的是,您不能在编译时检查所有内容。开发人员仍然有责任确保表达式真正返回映射属性。我尝试了使用EF4编写的代码,但它不起作用。方法Include是在ObjectQuery而不是ObjectSet上定义的。因此,它是查询对象上的一个扩展方法。它也应该适用于EF4.0,但前提是您使用设计器生成的类。它不适用于POCO实体,因为它们不是从
StructuralObject
继承的。不幸的是,它没有编译(.Net 4),因为
FixedWrappedMemberAcces
是未知的。啊,它是源代码复制和粘贴的牺牲品。。事实是,你不需要那条线。。这仅仅是为了解决包装字段的问题(有关更多信息,请参阅),但include不需要这样做。在EF4中,您可以包含EntityCollection,然后深入挖掘集合类型。您的解决方案支持吗?刚刚测试过&它可以工作!我有自跟踪实体(因为我不能在WCF场景中使用DbContext POCO实体)。它们是基于ObjectContext的,我只需添加EntityFramework引用(通过NuGet),将using行放在这里,就可以使用扩展Include方法了!问题是,我绝对没有理由添加EF4.1引用,除了对我的急切加载进行编译时检查。。。我想添加它是可以接受的,因为它只在服务器端使用?也许我会找到我将使用的其他扩展方法。EF4.1扩展方法只是解析您提供的表达式,然后将其转换为基于字符串的Include调用。因此,它有效地将上述示例转换为
.Include(“Orders.LineItems”)
。如果您真的不想安装EF4.1,那么您可能会找到其他编写了扩展方法的人来做同样的事情。在4.1之前,我写了我自己的(借用其他例子),我可以告诉你这不是很有趣。(表达式API…很奇怪。)我很高兴能够访问用于此的内置方法。
using System.Data.Entity; 
        db.Customers.Include(c => c.Orders.Select(o => o.LineItems))
var context = new DBContext();  
context.Organizations.Include(context.Assets.EntitySet.Name).Where(o => o.Id == id).Single()