mar*_*pet 53 t4 entity-framework ef-code-first entity-framework-5 ef-power-tools
我正在使用带有Entity Framework Power Tools Beta 2的Visual Studio的Entity Framework 5来反向设计中等大小的数据库(~100个表).
不幸的是,导航属性没有有意义的名称.例如,如果有两个表:
CREATE TABLE Contacts (
ContactID INT IDENTITY (1, 1) NOT NULL,
...
CONSTRAINT PK_Contacts PRIMARY KEY CLUSTERED (ContactID ASC)
}
CREATE TABLE Projects (
ProjectID INT IDENTITY (1, 1) NOT NULL,
TechnicalContactID INT NOT NULL,
SalesContactID INT NOT NULL,
...
CONSTRAINT PK_Projects PRIMARY KEY CLUSTERED (ProjectID ASC),
CONSTRAINT FK_Projects_TechnicalContact FOREIGN KEY (TechnicalContactID)
REFERENCES Contacts (ContactID),
CONSTRAINT FK_Projects_SalesContact FOREIGN KEY (SalesContactID)
REFERENCES Contacts (ContactID),
...
}
Run Code Online (Sandbox Code Playgroud)
这将生成如下类:
public class Contact
{
public Contact()
{
this.Projects = new List<Project>();
this.Projects1 = new List<Project>();
}
public int ContactID { get; set; }
// ...
public virtual ICollection<Project> Projects { get; set; }
public virtual ICollection<Project> Projects1 { get; set; }
}
public class Project
{
public Project()
{
}
public int ProjectID { get; set; }
public int TechnicalContactID { get; set; }
public int SalesContactID { get; set; }
// ...
public virtual Contact Contact { get; set; }
public virtual Contact Contact1 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我看到几个变体都比这更好:
FK_Projects_TechnicalContact- > TechnicalContact)之后的所有内容.虽然这可能是具有最多控制权的解决方案,但这可能更难以与现有模板集成.ID(TechnicalContactID- > TechnicalContact)TechnicalContactIDProjects(集合)和TechnicalContactIDContact幸运的是,可以通过将模板包含在项目中来修改模板.
这些修改必须要进行Entity.tt和Mapping.tt.由于缺乏智能感知和调试可能性来进行这些更改,我觉得很难.
连接属性名称(上面列表中的第三个)可能是最容易实现的解决方案.
如何更改导航属性的创建Entity.tt并Mapping.tt实现以下结果:
public class Contact
{
public Contact()
{
this.TechnicalContactIDProjects = new List<Project>();
this.SalesContactIDProjects = new List<Project>();
}
public int ContactID { get; set; }
// ...
public virtual ICollection<Project> TechnicalContactIDProjects { get; set; }
public virtual ICollection<Project> SalesContactIDProjects { get; set; }
}
public class Project
{
public Project()
{
}
public int ProjectID { get; set; }
public int TechnicalContactID { get; set; }
public int SalesContactID { get; set; }
// ...
public virtual Contact TechnicalContactIDContact { get; set; }
public virtual Contact SalesContactIDContact { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Rik*_*erg 48
您需要在.tt文件中更改一些内容.我选择使用您建议的第三种解决方案,但这需要格式化为FK_CollectionName_RelationName.我用'_'将它们拆分并使用数组中的最后一个字符串.我使用RelationName和ToEndMember属性来创建属性名称.FK_Projects_TechnicalContact将导致
//Plularized because of EF.
public virtual Contacts TechnicalContactContacts { get; set; }
Run Code Online (Sandbox Code Playgroud)
你的项目就是这样的.
public virtual ICollection<Projects> SalesContactProjects { get; set; }
public virtual ICollection<Projects> TechnicalContactProjects { get; set; }
Run Code Online (Sandbox Code Playgroud)
现在你可能要问的代码.我CodeStringGenerator在T4文件中为类添加了2个函数.构建propertyName的一个接收NavigationProperty.另一个生成接收NavigationProperty属性的代码和属性的名称.
//CodeStringGenerator class
public string GetPropertyNameForNavigationProperty(NavigationProperty navigationProperty)
{
var ForeignKeyName = navigationProperty.RelationshipType.Name.Split('_');
var propertyName = ForeignKeyName[ForeignKeyName.Length-1] + navigationProperty.ToEndMember.Name;
return propertyName;
}
public string NavigationProperty(NavigationProperty navigationProperty, string name)
{
var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} {2} {{ {3}get; {4}set; }}",
AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
name,
_code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
}
Run Code Online (Sandbox Code Playgroud)
如果您将上述代码放在课程中,您仍需要更改2个部分.您需要找到构造函数部分和导航属性部件正在构建实体的位置.在构造函数部分(第60行),您需要通过调用方法替换现有代码GetPropertyNameForNavigationProperty并将其传递给escape方法.
var propName = codeStringGenerator.GetPropertyNameForNavigationProperty(navigationProperty);
#>
this.<#=code.Escape(propName)#> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())#>>();
<#
Run Code Online (Sandbox Code Playgroud)
在NavigationProperties部分(第100行)中,您还需要使用以下代码替换代码.
var propName = codeStringGenerator.GetPropertyNameForNavigationProperty(navigationProperty);
#>
<#=codeStringGenerator.NavigationProperty(navigationProperty, propName)#>
<#
Run Code Online (Sandbox Code Playgroud)
我希望这会GetPropertyNameForNavigationProperty有所帮助,您可以随时调试该功能并使用该属性的命名进行一些操作.
基于BikeMrown的答案,我们可以使用RelationshipNameMSSQL中设置的属性将Intellisense添加到属性中:
在VS Project中编辑model.tt,然后更改:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
<#
}
#>
<#=codeStringGenerator.NavigationProperty(navigationProperty)#>
<#
}
}
Run Code Online (Sandbox Code Playgroud)
对此:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
<#
}
#>
/// <summary>
/// RelationshipName: <#=code.Escape(navigationProperty.RelationshipType.Name)#>
/// </summary>
<#=codeStringGenerator.NavigationProperty(navigationProperty)#>
<#
}
}
Run Code Online (Sandbox Code Playgroud)
值得注意的是,如果更改数据库模型,属性可能会发现自己指向不同的数据库字段,因为EF会根据各自的数据库字段名称的字母优先级生成导航属性名称!
| 归档时间: |
|
| 查看次数: |
11815 次 |
| 最近记录: |