4

我有几个从“用户”表到“报告”表的导航属性。生成的导航属性显然是这样访问的:

USER.REPORTs.Where(x => ...)
USER.REPORTs2.Where(x => ...)
USER.REPORTs3.Where(x => ...)

第一个是用户 createdId,第二个是 UserApprovedId 等等......基本的东西。

这些是极难解释的。如果不访问 EDMX 并检查导航属性,很难判断您正在导航哪个属性。

现在我知道我可以在属性管理器中创建自己的 End1/End2 导航属性,但如果重新创建模型,这些属性就会丢失。

有没有解决的办法?

4

5 回答 5

5

我没有尝试过,但这里有一个想法:既然所有实体类型都是部分类,为什么不将 Visual Studio 生成的导航属性包装在另一个具有方便名称的属性中?

在您的设计器文件中,您将拥有如下内容:

public partial class MyEntity : EntityObject
{
    #region Navigation Properties
    public EntityCollection<MyOtherEntity> Other_Entities1
    {
        // ...
    }
    #endregion
}

然后,您可以创建另一个文件来包装导航属性:

public partial class MyEntity
{
    public EntityCollection<MyOtherEntity> OtherEntities
    {
        get { return Other_Entities1;}
    }
}

您将在整个代码中使用上面的属性,并且由于在 Visual Studio 生成.edmx文件时使用相同的逻辑,因此包装的属性不会更改。即使包装的属性会更改其名称,您也需要在一个地方调整代码。

于 2012-05-14T09:32:23.893 回答
1

我想我有同样的问题,我从你的问题中了解到。

您希望保持导航属性名称尽可能清晰,但无论何时从 edmx 重新创建模型?!

其实我希望如果有更好的解决方案,但这里我在做什么:

  1. 将您在数据库中的关系命名为 : FK_Users_CreateUserReportFK_Users_ApprovedUserReport... 或任何合适的名称,然后我们将重命名导航属性ApprovedUserReportCreateUserReport等等...
  2. 每当您重新创建模型时创建一个帮助代码来执行,此代码将打开您的 edmx 文件并更新您想要的所有导航属性,如下所示:

    // file here is the path to your edmx file
    if (!string.IsNullOrEmpty(file))
    {
        var ns = XNamespace.Get("http://schemas.microsoft.com/ado/2008/09/edm");
        var doc = XDocument.Load(file);
        var list = (from xElem in doc.Descendants(ns + "NavigationProperty")
                    where xElem.Attribute("Name").Value.StartsWith("REPORTs"))
                    select xElem).ToList();
        foreach (var item in list)
        {
            var newName = item.Attribute("Relationship").Value.Split('_').LastOrDefault();
            if (!newName.Contains("."))
                item.SetAttributeValue("Name", newName);
            else
            {
                var ss = newName.Split('.').LastOrDefault();
            }
        }
        doc.Save(file);
        MessageBox.Show(list.Count.ToString());
    }
    

最后一件事,如果你使用纯代码模式,那么这个问题就消失了,但在这种情况下,你应该手动保持你的模型与你的数据库一致。

于 2012-05-10T09:02:44.687 回答
1

我不确定我是否正确理解了您的问题,但听起来您只是想要一种“更清洁”的方式来直接从 USER 对象访问 REPORTs.Where(...) LINQ 查询的结果。如果是这种情况,我建议像这样创建 USER 对象的扩展:

public static class UserExtensions
{
 public static List<REPORT> ReportsWithSomeCondition(this USER user)
 {
    return user.REPORTs.Where(...).ToList();
 }
}

您可以干净地调用它的方式是:

List<REPORT> results = USER.ReportsWithSomeCondition()

如果我完全错过了重点,请澄清您的问题,我将删除此答案。

于 2012-05-09T17:13:26.123 回答
0

您必须使用部分类机制将所有自定义实体代码放在单独的代码文件中。这允许生成生成的代码,而不会影响您的自定义代码。

于 2012-05-15T09:34:05.313 回答
0

Wahid 的答案似乎是长期维护的最佳答案。我们考虑在部分类中实现接口属性,我们将其用作“伙伴类”以进行扩展和设置元数据链接。但是我们正在接口的 T4 模板中的属性仍然是公共的,它们应该是私有的。

改进瓦希德的建议;我们选择扩展它们,而不是改变我们命名外键关系的标准。

FK_Users_Report_CreateUserReport 实际上是我们的解决方案。前 2 个值的标准命名约定得到维护,在更新模型代码中,您可以强制它仅更改带有第三个下划线和第三个值的导航属性名称。如果其他导航属性名称不遵循数据库中外键的标准命名约定,请确保它们不会影响任何其他导航属性名称。

于 2013-12-20T17:24:17.110 回答