修改 - 清理问题以更好地反映实际问题:
我正在使用SQLMetal从我们的SQL Server数据库生成数据库类。最近,我需要添加一个表,其中有多个外键指向同一个表。使用LINQPad来使用新表,我能够访问两个外键的属性,如下所示:
......这正是我所期待的。问题是,SQLMetal生成的类产生了这些属性:
现在我可能只能生成生成的类,因此FKBTableNameGoesHere将是FK_B,但生成的文件经常被不同的团队成员更改,因此这将是一个巨大的痛苦。对此有一个简单的解决方法吗?
提前致谢。
编辑2 所以,我认为解决方案是创建一个具有名为我想要的属性的部分类,并让getter / setter指向命名不佳的属性。这有助于选择,但不能在where子句中使用它。任何人都有解决方案??
答案 0 :(得分:4)
所以,我的解决方案是添加另一个部分类并添加一个属性,其中get / set指向奇怪命名的FKBTableNameGoesHere属性。这样我们就不必继续修改生成的类了。不完全解决问题,但应该让开发人员更清楚属性意味着什么。有人发现该解决方案存在任何潜在问题吗?
编辑 - 显然,这仅适用于选择数据而不是基于它的过滤。不像我希望的那样容易修复。有人有任何其他建议吗?
编辑2 - Jeeze,认为这会是一个常见的问题,但我想不是。无论如何,事实证明我是在正确的轨道上。我找到了这篇文章:
Multiple foreign keys to the same table
这给了我一个想法,我不能直接链接到另一个属性的getter / setter,因为它可能比幕后更多。这个家伙解决方案并不完全是答案,但它让我处于严谨的方向。添加关联属性是最终做到的:
public partial class ProblemClass
{
[Association(Name = "FK__SomeLinkHere", Storage = "_OriginalPoorlyNamedStorageVariable", ThisKey = "FK_1_Id", OtherKey = "Id", IsForeignKey = true)]
public FKType MyNewBetterName
{
get
{
return this._OriginalPoorlyNamedStorageVariable.Entity;
}
set
{
this.OriginalPoorlyNamedStorageVariable = value;
}
}
}
为那些仍能提出更清洁解决方案的人打开奖金。
答案 1 :(得分:0)
好的,即使关联名称发生变化,我也会提出一个新的答案(很晚,很抱歉)。
此方法将查找主实体的关联属性,然后它将查找主表中的值。想象一下:
表Orders
由Customers
引用Orders.CustomerID
等于Customers.Id
。因此,我们传递主表的元信息,字段CustomerID
(引用字段)和字段Name
(这是我们想要的值)。
/// <summary>
/// Gets the value of "referencedValueFieldName" of an associated table of the "fieldName" in the "mainTable".
/// This is equivalent of doing the next LINQ query:
/// var qryForeignValue =
/// from mt in modelContext.mainTable
/// join at in modelContext.associatedTable
/// on mt.fieldName equals at.associatedField
/// select new { Value = at.referencedValueField }
/// </summary>
/// <param name="mainTable">Metadata of the table of the fieldName's field</param>
/// <param name="fieldName">Name of the field of the foreign key</param>
/// <param name="referencedValueFieldName">Which field of the foreign table do you the value want</param>
/// <returns>The value of the referenced table</returns>
/// <remarks>This method only works with foreign keys of one field.</remarks>
private Object GetForeignValue(MetaTable mainTable, string fieldName, string referencedValueFieldName) {
Object resultValue = null;
foreach (MetaDataMember member in mainTable.RowType.DataMembers) {
if ((member.IsAssociation) && (member.Association.IsForeignKey)) {
if (member.Association.ThisKey[0].Name == fieldName) {
Type associationType = fPointOfSaleData.GetType();
PropertyInfo associationInfo = associationType.GetProperty(member.Name);
if (associationInfo == null)
throw new Exception("Association property not found on member");
Object associationValue = associationType.InvokeMember(associationInfo.Name, BindingFlags.GetProperty, null, fPointOfSaleData, null);
if (associationValue != null) {
Type foreignType = associationValue.GetType();
PropertyInfo foreignInfo = foreignType.GetProperty(referencedValueFieldName);
if (foreignInfo == null)
throw new Exception("Foreign property not found on assiciation member");
resultValue = foreignType.InvokeMember(foreignInfo.Name, BindingFlags.GetProperty, null, associationValue, null);
}
break;
}
}
}
return resultValue;
}
电话:
AttributeMappingSource mapping = new System.Data.Linq.Mapping.AttributeMappingSource();
MetaModel model = mapping.GetModel(typeof(WhateverClassesDataContext));
MetaTable table = model.GetTable(typeof(Order));
Object value = GetForeignValue(table, "CustomerId" /* In the main table */, "Name" /* In the master table */);
问题是只能使用只有一个引用字段的外键。但是,更改为多个键非常简单。
这是获取主表字段值的方法,可以更改为返回整个对象。
PS:我觉得我的英语犯了一些错误,这对我来说很难。答案 2 :(得分:0)
很久以前出现了这个问题,但我刚遇到这个问题。我正在使用DBML,我通过编辑关系解决了这个问题。如果展开ParentProperty,可以通过更改Name属性来设置属性名称。
这是来自DBML的XML(会员属性已更改):
<Association Name="State_StateAction1" Member="DestinationState" ThisKey="DestinationStateId" OtherKey="Id" Type="State" IsForeignKey="true" />
答案 3 :(得分:0)
以下是Ocelot20版本的变体:
public partial class ProblemClass
{
partial void OnCreated()
{
this._MyNewBetterName = default(EntityRef<FKType>);
}
protected EntityRef<FKType> _MyNewBetterName;
[Association(Name = "FK__SomeLinkHere", Storage = "_MyNewBetterName", ThisKey = "FK_1_Id", OtherKey = "Id", IsForeignKey = true)]
public EntityRef<FKType> MyNewBetterName
{
get
{
return this._MyNewBetterName.Entity;
}
set
{
this.MyNewBetterName = value;
}
}
}
有了这个,你甚至不需要知道原始的存储名称,但是我不确定setter是否可以工作(我只使用了getter,但它就像魅力一样)。您甚至可以将此关系定义打包到基类并使其部分继承它(如果您需要重用多个模型\上下文中的关系,这应该会更容易),但是问题是,您必须定义{{1在每个部分内部,因为那些不能在c#(see this)中继承。