8 Stimmen

Wie kann die PetaPoco-Klasse geändert werden, um mit einem zusammengesetzten Schlüssel zu arbeiten, der aus nicht-numerischen Spalten besteht?

Ich habe eine Tabelle mit folgenden Spalten:

ContractorId ......... INT ............. IDENTITY
ContractorName ........ Varchar(50) ....... P.K
ContractorGrade ....... Varchar(3) ....... P.K

Die Klasse, die vom PetaPoco T4 Template generiert wird, sieht folgendermaßen aus:

[TableName("contractor_master")]
[PrimaryKey("contractorname", autoIncrement=false)]
[ExplicitColumns]
public partial class contractor_master : TubewellRepo.Record  
{
    [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;
  }

Der Code zum Einfügen eines neuen Datensatzes lautet wie folgt:

// Einen Datensatz einfügen
var Contractor=new contractor_master();
Contractor.contractorname = "Super Borewells";
Contractor.contractorgrade = "A";

db.Insert(Contractor);

In der zweiten Zeile des Klassen-Codes möchte ich wissen, wie ein zusammengesetzter Schlüssel (ContractorName + ContractorGrade) angegeben werden kann.

Zweitens wird kein Datensatz eingefügt, weil es eine ID-Spalte erwartet. Auch wenn ContractorId IDENTITY ist, ist es kein Primärschlüssel.

Es wird kein neuer Datensatz EINGEFÜGT und es tritt ein Fehler auf, weil 0 in die IDENTITY-Spalte eingefügt wird.

7voto

Schotime Punkte 15287

Mein Zweig hier: https://github.com/schotime/petapoco unterstützt den zusammengesetzten Primärschlüssel durch Angabe des PrimaryKey-Attributs wie:

[PrimaryKey("ContractorName,ContractorGrade")]

Ich bin mir nicht sicher, wie es funktionieren wird, wenn Sie auch die Identitätsspalte dort haben möchten.

2voto

Cirem Punkte 820

Ich musste die folgenden Änderungen vornehmen, um IsNew() zu unterstützen.

// Überprüfen, ob ein POCO einen neuen Datensatz darstellt
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("Das Objekt hat keine Eigenschaft, die mit dem Primärschlüsselspaltennamen '{0}' übereinstimmt",
                          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)
    {
        // Gemeinsame Typen von Primärschlüsseln
        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);

        // Erstellen einer Standardinstanz und Vergleich
        return pk == Activator.CreateInstance(pk.GetType());
    }
    else
    {
        return pk == null;
    }
}

0voto

ulu Punkte 5482

Ich sehe, dass es jetzt den CompositeKeySuppport-Zweig gibt, also ist es wahrscheinlich, dass dies bald im offiziellen Repository unterstützt wird, was bedeutet, dass wir NuGet-Updates und so weiter erhalten werden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X