Unless these objects share a common interface you'll have to use reflection to get the properties of an object, then loop through them and compare the values between objectA and objectB. Something like this:
public void CompareTwoObjectsAndSaveChanges<TObjectType>(TObjectType objectA, TObjectType objectB )
{
//makes sure both objects match in Type
if(objectA.GetType() == objectB.GetType())
{
//uses reflection to get all the properties of that object.
foreach (var prop in objectA.GetType().GetProperties())
{
//checks to see if the value is different
if(prop.GetValue(objectA, null) != prop.GetValue(objectB, null))
{
//get the property name and its two different values
string nameOfPropertyThatChanges = prop.Name;
string objectAValue = prop.GetValue(objectA, null).ToString();
string objectBValue = prop.GetValue(objectB, null).ToString();
//logic to save to database
}
}
}
}
You'll have to have oldValue and newValue columns be set to varchar or nvarchar in the database and convert all property values to strings before saving, otherwise you can't do what you are asking. Technically you wouldn't even have to use generics here as both parameters could simply take an object and the reflection would still work AS LONG AS both objects were the same type. The generic parameter here just makes it a bit more clean and makes sure that the person calling this method can't pass in two objects of different types accidently.
EDIT: To get the name of the object for your first table you would do:
typeof(TObjectType).ToString();