【问题标题】:Find Foreign Keys from a T4 Template generator从 T4 模板生成器中查找外键
【发布时间】:2023-04-06 20:16:01
【问题描述】:

我正在尝试为我的实体中的每个外键生成一个方法,以根据该外键返回记录列表。我知道一种确定主键的方法:

foreach (var edmProperty in simpleProperties)
{
    bool isPrimaryKey = ef.IsKey(edmProperty);
    if(isPrimaryKey)
    {
       //do stuff
    }
}

有没有办法找到外键? 我将 EF 6 与 Visual Studio 2013 一起使用。 谢谢

【问题讨论】:

  • "返回记录列表" ...这就是集合导航属性的用途。我不确定你想要达到什么目的。
  • 假设我有一个产品。我的产品有一个 categoryID 作为外键。我想用我的 T4 模板生成一个方法来返回具有给定 categoryID 的所有产品。当我在我的实体的 T4 模板中循环浏览所有属性时,如何判断哪个属性是外键,以便创建此方法。我可以弄清楚哪个是主键而不是外键。
  • 为什么是方法?在哪个班? Category 将有一个导航属性 Products
  • 我想在生成的代码中添加一个方法,这样我的代码隐藏中就没有我的上下文了。这将适用于我的模型中从实体框架(数据库优先模型)生成的所有类。我想我可以从 Category 类中获取它,但是如果我想要返回产品,我将不得不创建一个自定义方法,如 ctx.Categories.Include("Products").ToList() 。或者在我的代码隐藏中包含上下文,以便在我访问类别时自动加载产品。
  • 你为什么不展示一个例子来说明这种方法应该是什么样子?我仍然不清楚,主要是因为你从来不知道这些方法应该属于哪里以及它们应该如何操作。

标签: visual-studio-2013 entity-framework-6 t4 asp.net-4.0


【解决方案1】:

不要这样做。有很多原因:

  • 它打破了持久性无知。 POCO 不应该对数据层一无所知。您甚至可以在不引用 EF 的单独程序集中定义 POCO。
  • GetByCountryID 等方法通常是存储库方法,它们不属于实体类。
  • 静态方法不应分散在类模型中。它们是实用程序类或工厂的典型代表(使用 City.New() 之类的方法可能很有意义)。
  • 你怎么知道City 有一个GetByCountryID 方法?甚至可能有更多类具有相同的方法。
  • 通过该方法获得的对象与City 实例没有任何关系,但它的位置似乎意味着这种关联。
  • 如果您从 EDMX 中删除属性 Country(例如,因为它从未使用过),该方法也会消失。
  • 主要原因:导航属性无可替代。如果您想获得Categories 他们的Products,您必须以 EF 知道如何关联它们的方式加载它们。您可以通过Include 执行此操作,或者将它们包含在投影中,或者通过延迟加载,或者稍后获取Products,但所有在同一上下文中。您提出的方法只能产生分离的实体,并且也断开连接(即不附加到上下文)。

还有其他模式可以向其他应用程序层隐藏数据层详细信息,例如具有依赖注入的存储库。

【讨论】:

  • 我明白你的意思......但是你的代码隐藏中没有你的上下文是一个坏主意,因为它与你的 UI 相关联?我想这就是您对存储库和依赖注入的建议的用武之地......不太熟悉这种模式。
  • 如果您的实体没有引用上下文,为什么还要将上下文绑定到 UI?例如,如果您有一个返回实体的服务层,则服务之外的任何人都不需要了解 EF。
  • 当您说“您有一个返回实体的服务层,服务之外的任何人都不需要了解 EF”...我是否需要在 T4 模板生成的内容之上再添加一层?我在想与我的实体交互并将对象返回到我的 UI 的方法(由 T4 模板生成)是我的服务层。如果我把: using(MyEntities ctx = new MyEntities()) { //do stuff with my context } ...在我的代码隐藏中,那么我的 UI 直接绑定到数据层。如果我没有关注,我深表歉意。
  • 是的,在这种情况下,UI 引用了 EF。这不一定是坏事,但通常你会在一个单独的程序集中创建一个服务层,其中可能有像ProductService 这样的类,具有像GetProducts(some specification)CreateProduct(some other specification, or a Product entity) 这样的方法。这些服务可以直接与 EF 进行通信,也可以通过存储库进行通信,尽管我不喜欢后者。
  • 谢谢格特。我明白你在说什么。我试图实现的结果是通过我的 T4 模板创建这些 GetProducts() 和 CreateProduct() 方法,但我可能应该将生成的代码保持原样并为此添加另一层。谢谢
【解决方案2】:

这是获取外键属性名称的方法。

public IEnumerable<NavigationProperty> GetParentNavigationProperties(EntityType type)
{
    return type.NavigationProperties.Where(np => np.DeclaringType == type && np.ToEndMember.RelationshipMultiplicity != RelationshipMultiplicity.Many);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-07
    • 2011-10-16
    • 2013-10-03
    • 2011-05-31
    • 1970-01-01
    • 2012-09-06
    • 2014-06-13
    • 2010-12-17
    相关资源
    最近更新 更多