如何修改 PetaPoco 类以使用由非数字列组成的复合键?
Posted
技术标签:
【中文标题】如何修改 PetaPoco 类以使用由非数字列组成的复合键?【英文标题】:How to modify PetaPoco class to work with Composite key comprising of non-numeric columns? 【发布时间】:2012-06-25 12:24:02 【问题描述】:我有一个包含以下列的表格:
ContractorId ......... INT ................ IDENTITY 承包商名称 ........ Varchar(50) ....... P.K ContractorGrade ....... Varchar(3) ....... P.K
PetaPoco T4 模板生成的类如下所示:
[TableName("contractor_master")]
[PrimaryKey("contractorname", autoIncrement=false)]
[ExplicitColumns]
public partial class contractor_master : TubewellRepo.Record<contractor_master>
[Column]
public int contractorid
get
return _contractorid;
set
_contractorid = value;
MarkColumnModified("contractorid");
int _contractorid;
[Column]
public string contractorname
get
return _contractorname;
set
_contractorname = value;
MarkColumnModified("contractorname");
string _contractorname;
[Column]
public string contractorgrade
get
return _contractorgrade;
set
_contractorgrade = value;
MarkColumnModified("contractorgrade");
string _contractorgrade;
插入新记录的代码如下:
// Insert a record
var Contractor=new contractor_master();
Contractor.contractorname = "Super Borewells";
Contractor.contractorgrade = "A";
db.Insert(Contractor);
在Class Code的第二行,我想知道如何提及一个复合键,即(ContractorName + ContractorGrade)。
其次,它没有插入记录,因为它需要一个 Id 列。即使 ContractorId 是 IDENTITY,它也不是主键。
它没有插入新记录并给出错误,因为它在 IDENTITY 列中插入了 0。
【问题讨论】:
如果您已经有一个ContractorId
列,为什么不让 PetaPoco 将其用作主键呢?您仍然可以将复合键保留在数据库中。
好的。但只是想知道 PetaPoco 是否支持 Composite Key。
【参考方案1】:
我的分店:https://github.com/schotime/petapoco 通过指定 PrimaryKey 属性支持复合主键,如:
[PrimaryKey("ContractorName,ContractorGrade")]
我不确定如果您还想要标识列,它将如何工作。
【讨论】:
我试过了,但它不支持 IsNew(..) 方法,你能更新一下吗? 不错!我很惊讶在这么长时间之后它还没有被拉回主项目。【参考方案2】:我必须进行以下更改以支持 IsNew()
// Check if a poco represents a new record
public bool IsNew(string primaryKeyName, object poco)
var pd = PocoData.ForObject(poco, primaryKeyName);
object pk;
PocoColumn pc;
if (pd.Columns.TryGetValue(primaryKeyName, out pc))
pk = pc.GetValue(poco);
#if !PETAPOCO_NO_DYNAMIC
else if (poco.GetType() == typeof(System.Dynamic.ExpandoObject))
return true;
#endif
else if (primaryKeyName.Contains(","))
return primaryKeyName.Split(',')
.Select(pkPart => GetValue(pkPart, poco))
.Any(pkValue => IsDefaultOrNull(pkValue));
else
pk = GetValue(primaryKeyName, poco);
return IsDefaultOrNull(pk);
private static object GetValue(string primaryKeyName, object poco)
object pk;
var pi = poco.GetType().GetProperty(primaryKeyName);
if (pi == null)
throw new ArgumentException(
string.Format("The object doesn't have a property matching the primary key column name '0'",
primaryKeyName));
pk = pi.GetValue(poco, null);
return pk;
private static bool IsDefaultOrNull(object pk)
if (pk == null)
return true;
var type = pk.GetType();
if (type.IsValueType)
// Common primary key types
if (type == typeof(long))
return (long)pk == default(long);
else if (type == typeof(ulong))
return (ulong)pk == default(ulong);
else if (type == typeof(int))
return (int)pk == default(int);
else if (type == typeof(uint))
return (uint)pk == default(uint);
else if (type == typeof(Guid))
return (Guid)pk == default(Guid);
// Create a default instance and compare
return pk == Activator.CreateInstance(pk.GetType());
else
return pk == null;
【讨论】:
实际上 IsNew 用于决定是否需要插入或更新。在 PetaPoco 中,它说“IsNew() 和 Save() 仅在具有自动递增/标识主键列的表上受支持”我相信它需要许多其他工作,例如复合键的自动递增/进行 Select 以查看它是否是真正的新钥匙。这个方法不需要修改【参考方案3】:我可以看到现在有 CompositeKeySuppport branch,所以我们很有可能很快会在官方 repo 中支持它,这意味着我们将获得 NuGet 更新和东西。
【讨论】:
以上是关于如何修改 PetaPoco 类以使用由非数字列组成的复合键?的主要内容,如果未能解决你的问题,请参考以下文章