Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify PetaPoco class to work with Composite key comprising of non-numeric columns?

Tags:

c#

.net

petapoco

I have a table with following columns:

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

The class generated by PetaPoco T4 template looks like this:

[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;
  }

The code to INSERT a new record is as below:

// Insert a record
var Contractor=new contractor_master();
Contractor.contractorname = "Super Borewells";
Contractor.contractorgrade = "A";

db.Insert(Contractor);

In the second line of the Class Code, I want to know how to mention a Composite Key, which is (ContractorName + ContractorGrade).

Secondly, it is not inserting a record because it expects an Id column. Even though ContractorId is IDENTITY, it is not a primary key.

It is not INSERTING a new record and gives error because it is inserting 0 in the IDENTITY column.

like image 812
RKh Avatar asked Jun 23 '12 11:06

RKh


People also ask

What is the limit for no of columns to be a composite primary key in sql3?

One table can have only one primary key. However, this primary key could be a single column or combination of more than one column as per the buisness requirements. No Limits.

How many columns can a composite key have?

Columns: The latest version of SQL supports the combining of more than 16 columns. The data type of the columns combined to make a composite key can be different for all the columns.

Can columns in relation Be composite?

A composite key, in the context of relational databases, is a combination of two or more columns in a table that can be used to uniquely identify each row in the table. Uniqueness is only guaranteed when the columns are combined; when taken individually the columns do not guarantee uniqueness.


2 Answers

My branch here: https://github.com/schotime/petapoco supports composite primary key by specifying the PrimaryKey attribute like:

[PrimaryKey("ContractorName,ContractorGrade")]

I'm not sure how it will work if you want the identity column there as well.

like image 90
Schotime Avatar answered Oct 21 '22 22:10

Schotime


I had to make the following changes to support 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;
            }
        }
like image 21
Cirem Avatar answered Oct 21 '22 20:10

Cirem