0

I am using Dapper.net as an ORM. I have an abstraact class called BusinessObject, which is inherited from by other classes that represent the tables in my database, for example SubContractorJob.

I have a method on the BusinessObject class called "Persist", which saves a record to the database:

public abstract class BusinessObject<T>
{
    public bool Persist<T>(IDbConnection db, T entity)
        where T : BusinessObject<T>, IDBObject
    {
        if (entity.Id > 0)
        {
            db.Update(entity);
            return true;
        }
        else
        {
            db.Insert(entity);
            return false;
        }
    }

}

Currently, as you can see, the Persist method takes an object as input.

Which means when I inherit from the BusinessObject class, I have to call it like this from my child object:

IDbConnection db = DBConnection.GetConnection();

    SubContractorJob s = new SubContractorJob()
            {
                Id = 3,
                SubContractorId = 6,
                JobId = 8,
                StartDate = DateTime.Today,
                EndDate = DateTime.Today.AddDays(10),
                EstimatedCost = 20000,
                ActualCost = 18000,
                IsDeleted = true
            }; 

s.Persist<SubContractorJob>(db, s);

My question is: How can I make this work without having to pass 's' when I am already calling the method in the context of s (the child object)?

I do have an interface (IDBObject) set up, so the child object is always guaranteed to have the Id field present.

I tried this:

public bool Persist<T>(IDbConnection db)
            where T : BusinessObject<T>, IDBObject
        {
            if ((typeof(T) as IDBObject).Id > 0)
            {
                db.Update(this);
                return true;
            }
            else
            {
                db.Insert(this);
                return false;
            }
        }

But got this error:

System.NullReferenceException : Object reference not set to an instance of an object.

Thanks for your help!

6
  • What happens if you move where T : BusinessObject<T>, IDBObject to the BusinessObject class definition? Commented Dec 10, 2017 at 12:50
  • @mjwills, I did that and ran the "if ((typeof(T) as IDBObject).Id > 0)" version of the method and it failed with the same error. Is that what you were thinking I should do? Commented Dec 10, 2017 at 12:56
  • Use if (this.Id > 0) not if ((typeof(T) as IDBObject).Id > 0). The latter makes no sense since the latter is trying to cast the Type not the object itself. I suspect you meant to do if ((this as IDBObject).Id > 0), but even that as is unnecessary if you move the constraint to the class as I suggested earlier. Commented Dec 10, 2017 at 13:01
  • @mjwills, thanks for the clarification. The problem I am having is that the compiler doesn't recognize this.Id as a valid field. Commented Dec 10, 2017 at 13:07
  • @mjwills, I just tried if ((this as IDBObject).Id > 0) and it does exactly what I want! There is no Id field on my BusinessObject class; only the child class implements the interface. However, I am happy to use the solution above; it does what I need. Commented Dec 10, 2017 at 13:11

1 Answer 1

3
if ((typeof(T) as IDBObject).Id > 0)

should be changed to:

if ((this as IDBObject).Id > 0)

The primary issue with your original code is that you are trying to cast a Type (from typeof) to IDBObject, rather than an object.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.