I have a class named BaseDAL, this is the parent class. AuthorDAL class, ReaderDAL will inherit from BaseDAL class. The BaseDAL class has functions loadDataAsync(), insertAsync..., these functions will call a data query function in the DataProvider, this query function has 1 parameter as the name of a procedure. I tried creating a virtual variable zProceduceName and having subclasses overwrite that variable. But I realized that if I do that, every time I call the function differently, I will change the value of that variable to the new procedure name. What I need to do:
- Modified the functions in BaseDAL so that I don't need to use the zProceduceName variable to pass the procedure
This is BaseDAL code:
protected virtual string zProceduceName { get; set; }
public virtual async Task<DataTable> loadDataAsync()
{
return await DataProvider.Instance.executeQueryAsync(zProceduceName);
}
public virtual async Task insertAsync(string pzName, string pzAddress, string pzEmail, string pzPhone, CancellationToken pCt)
{
await DataProvider.Instance.executeNonQueryAsync(zProceduceName,pCt, new object[] {pzName,pzAddress,pzEmail,pzPhone});
}
public virtual async Task updateAsync( int pnID ,string pzName, string pzAddress, string pzEmail, string pzPhone, CancellationToken pCt)
{
await DataProvider.Instance.executeNonQueryAsync(zProceduceName, pCt, new object[] {pnID,pzName,pzAddress,pzEmail,pzPhone});
}
public virtual async Task deleteAsync( int pnID,CancellationToken pCt)
{
await DataProvider.Instance.executeNonQueryAsync(zProceduceName,pCt, new object[] { pnID});
}
And this is the AuthorDAL code:
public override async Task<DataTable> loadDataAsync()
{
zProceduceName = "dbo.LoadAuthor";
await DataProvider.Instance.executeQueryAsync(zProceduceName);
return await base.loadDataAsync();
}
public override async Task insertAsync( string pzName, string pzAddress, string pzEmail, string pzPhone, CancellationToken pCt)
{
zProceduceName = "dbo.InsertAuthor @name , @address , @email , @phone";
await DataProvider.Instance.executeNonQueryAsync(zProceduceName, pCt, new object[] { pzName, pzAddress, pzEmail, pzPhone });
await base.insertAsync(pzName, pzAddress, pzEmail, pzPhone, pCt);
}
public override async Task updateAsync(int pnID, string pzName, string pzAddress, string pzEmail, string pzPhone, CancellationToken pCt)
{
zProceduceName = "dbo.UpdateAuthor @id , @name , @address , @email , @phone";
await DataProvider.Instance.executeNonQueryAsync(zProceduceName, pCt, new object[] { pnID, pzName, pzAddress, pzEmail, pzPhone });
await base.updateAsync(pnID, pzName, pzAddress, pzEmail, pzPhone, pCt);
}
CodePudding user response:
Usually in c# you want to extend upon your base class, and replace only when necessary. This is why functions are not virtual by default. However if the variable values are the only difference you can use a factory to create a specific instance instead. However if the "BaseDAL" class should not be used directly you can use the concept of abstract classes. You should either:
- Add an abstract function to get the procedures' names
- Move calls to the DataProvider to protected functions and make all other functions abstract (calling the protected functions in the inheriting classes).
CodePudding user response:
You are needlessly over-relying on virtual inheritance. It seems the only purpose for the zProceduceName
is that you need to pass an additional parameter, and you can't change the signature because you are forcing yourself into inheritance.
public interface IDal
{
Task<DataTable> loadDataAsync();
Task insertAsync(string pzName, string pzAddress,
string pzEmail, string pzPhone, CancellationToken pCt);
Task updateAsync( int pnID ,string pzName,
string pzAddress, string pzEmail,
string pzPhone, CancellationToken pCt);
Task deleteAsync( int pnID,CancellationToken pCt);
}
public class AuthorDal : BaseDal, IDal
{
public async Task<DataTable> loadDataAsync()
{
return await base.loadDataAsync("dbo.LoadAuthor");
}
// etc. Methods are not "override" (but might need "new")
}
public class BaseDal
{
protected async Task<DataTable> loadDataAsync(string proceduceName)
{
return await DataProvider.Instance.executeQueryAsync(proceduceName);
}
// etc. methods are protected but not virtual with an extra parameter.
}