我正在尝试编写一些通用的 Linq to SQL 代码,基于实体的主键执行操作。我所处理的一些实体具有组合主键。
基本上,我想能够执行以下操作:
if( PrimaryKey(foo) == PrimaryKey(bar) ) ...
或者,
from oldEntity in oldTableOrCollection
join newEntity in newTableOrCollection
on PrimaryKeyOf(oldEntity) equals PrimaryKeyOf(newEntity)
select new {oldEntity, newEntity}
只要实体具有主键,就可以满足要求。
到目前为止,我找到了以下内容:
可以进行以下操作:
var query = from row in oneTableOfRows
join otherRow in anotherTableOfRows on
new { row.Column1, row.Column2 }
equals
new { otherRow.Column1, otherRow.Column2}
select ...;
在其中,linqtosql将使用匿名类型进行比较(前提是属性名称匹配)。
然后,我可以抽象出用于选择要连接的列的方法,以允许通用行类型:
void DoQuery<RowType,KeyType>(Table<RowType> oneTableOfRows,
Table<RowType> anotherTableOfRows,
Func<RowType, KeyType> keySelector)
{
var query = from row in oneTableOfRow
join otherRow in anotherTableOfRows on
keySelector(row)
equals
keySelector(otherRow)
select ...;
}
...
Func<rowType, keyType> myKeySelector = row => new { row.Column1, row.Column2 };
DoQuery(table, otherTable, myKeySelector);
我现在尝试转移到的是,keySelector将选择任何RowType的主键。我正在使用基于http://www.codeplex.com/l2st4的自定义模板来生成我的实体(它本身与VS中的默认模板相当相似)。
我希望能够为每个生成的RowType提供从dbml中获取其主键的能力。到目前为止,输出如下:
public interface IPrimaryKeyEntity<PrimaryKeyType>
{
PrimaryKeyType PrimaryKey { get; }
}
//Here, Product is a table with composite primary key based on its ProductID and it's ProductPriceVersionID columns
//I've tried using both class and struct as the primary key type for entities
public class ProductPrimaryKey
{
public Guid ProductID;
public Guid ProductPriceVersionID;
}
public partial class Product : IPrimaryKeyEntity<ProductPrimaryKey>,
INotifyPropertyChanging, INotifyPropertyChanged
{
#region IPrimaryKeyEntity Implementation
public ProductPrimaryKey PrimaryKey
{
get
{ return new ProductPrimaryKey()
{
ProductID = this.ProductID,
ProductPriceVersionID = this.ProductPriceVersionID
};
}
}
#endregion
...
//Rest is mostly standard LinqToSql entity generation
}
回到最初的目标,我现在可以为所有主键实体编译以下内容:
from oldEntity in oldTableOrCollection
join newEntity in newTableOrCollection
on oldEntity.PrimaryKey equals newEntity.PrimaryKey
select new {oldEntity, newEntity}
然而,在运行时,我遇到了臭名昭著的[PrimaryKey]“没有受支持的SQL翻译”的异常。
我知道要翻译成 SQL,需要使用,但我对非常不熟悉,尝试将其应用于我的情况还没有取得任何进展...
如果有人能改进我目前的做法或者有更好的方法,我将不胜感激。
谢谢。
Expression应该是一个很好的起点。它位于“非公共成员”>“queryExpression”下。我也是新手,但如果我发现什么,我会告诉您:) - Vladislav Zorov