Here's the situation:I have a common Data Access  assembly that contains classes used in all my projects.  Some of those are abstract classes that are only implemented by my data access layers for each project.In my projects I have a layered approach - separated data access, business layer, and UI.  My data access classes may inherit from the abstract classes in Common.  These abstract classes contain an execute method.In my business layer of the project I only reference the data access layer of the project - I don't reference other projects or the Common assembly.  But once I put my abstract classes that are reused all the time into Common, my business layer could no longer call the Execute method without having a reference to common.I hope that's not too confusing.If I don't want lots of interdependencies between assemblies, I need to move the abstract classes back into each project's data access layer.  But then I have repeated code and potentially inconsistent behavior between projects.But if I keep it as it is, all my business layers need to be able to access this common data access assembly, which seems wrong.Any thoughts on this architecture?I know some might try to say use Entity Framework or some other ORM.  But my projects are not complex enough to warrant that much overhead, especially given the need for fast performance.  I have found that a simple framework of my own directly implementing ADO.Net is remarkably faster.  So please just advise me on the separation of concerns and inheritance issues and don't try to talk me into adding an ORM.Example code:In Common: base classPublic MustInherit Class AbstractDatabaseAction    Protected Property Factory As DbProviderFactory    Protected Property Connection As DbConnection    Protected Property Command As DbCommand    Protected Property MessageForExceptions As String    Protected Property ProviderName As String    Protected Sub New(connString As String, providerName As String, messageForExceptions As String)        Factory = DbProviderFactories.GetFactory(providerName)        'set up connection        Connection = Factory.CreateConnection        Connection.ConnectionString = connString        Me.ProviderName = providerName        'set up command        Command = Factory.CreateCommand        Me.MessageForExceptions = messageForExceptions    End Sub    Public MustOverride Sub Execute()    Protected Overridable Sub SetParameters()        'nothing    End Sub    Protected MustOverride Sub SetCommandText()    Protected Overridable Sub SetCommandType()        Command.CommandType = CommandType.StoredProcedure    End Sub    Protected Sub BuildCommand()        Command.Connection = Connection        Me.SetCommandText()        Me.SetCommandType()        Me.SetParameters()        If Me.ProviderName = Oracle.DataAccess.Client Then            OracleSpecificCommandEdits()        End If    End Sub    Protected Overridable Sub OracleSpecificCommandEdits()        CType(Command, OracleCommand).BindByName = True    End SubEnd ClassIn Common: second base class (I have both a search and a save version, with the save version optionally allowing transactions.)Public MustInherit Class AbstractSearch    Inherits AbstractDatabaseAction    Protected Sub New(connString As String, providerName As String, messageForExceptions As String)        MyBase.New(connString, providerName, messageForExceptions)    End Sub    Public Overrides Sub Execute()        Try            Me.BuildCommand()            Using Connection                Connection.Open()                Using Command                    Try                        Dim rdr As IDataReader = Command.ExecuteReader                        Me.fill(rdr)                        rdr.Close()                    Catch ex As Exception                        Throw New Exception(MessageForExceptions & ->Search, ex)                    End Try                End Using            End Using        Catch ex As Exception            Throw New Exception(MessageForExceptions & ->Search, ex)        End Try    End Sub    Protected MustOverride Sub fill(ByRef rdr As System.Data.IDataReader)    Protected Overrides Sub OracleSpecificCommandEdits()        MyBase.OracleSpecificCommandEdits()        If TypeOf (Factory) Is OracleClientFactory Then            Dim p As DbParameter = New OracleParameter            p.ParameterName = results            p.Direction = ParameterDirection.Output            CType(p, OracleParameter).OracleDbType = OracleDbType.RefCursor            Command.Parameters.Add(p)        End If    End SubProtected Sub AddInParameter(key As String, value As Object)    Dim p As IDataParameter = Command.CreateParameter    p.Direction = ParameterDirection.Input    p.Value = value    p.ParameterName = key    Command.Parameters.Add(p)End SubProtected Sub AddOutParameter(key As String, type As System.Data.DbType)    Dim p As IDataParameter = Command.CreateParameter    p.Direction = ParameterDirection.Output    p.DbType = type    p.ParameterName = key    Command.Parameters.Add(p)End SubEnd ClassA very simple implementation example of a data access layer implementation:Public Class IpBlackListSearch        Inherits Common.DataAccess.AbstractSearch        Private Property IPToSearch As String        Public Property Results As List(Of String) = Nothing        Public Sub New(connString As String, providerName As String, ipAddressToSearch As String)            MyBase.New(connString, providerName, IpAddressSearch)            Me.IPToSearch = IPToSearch        End Sub        Protected Overrides Sub fill(ByRef rdr As System.Data.IDataReader)            Results = New List(Of String)            While rdr.Read                Results.Add(HelperFunctions.NullScrubber(Of String)(ip))            End While        End Sub        Protected Overrides Sub SetCommandText()            Command.CommandText = Get_IPBlacklist        End Sub        Protected Overrides Sub SetParameters()            MyBase.AddInParameter(in_ip, Me.IPToSearch)        End Sub    End ClassThe problem would come when in the business layer of my project that would do something like:Dim srch as new IpBlackListSearch(connstring, providername, 12.12.12.12.)srch.executesrch.Execute can only compile if the business layer references the common data access assembly. It sounds like from the comments that there is nothing wrong with my business layer containing that reference.  
Best Practices - separation of concerns and inheritance issues
design;.net;object oriented design
From what I understand your question to be, it seems like your Data Access Layer classes were accessing the Common Assembly and then your Business Layer accessed your Project Specific Data Access Layer.Now you want to put some of your Common Data Access layer classes into the Common Assembly. You think it is no longer OK for the Business Layer to access the DAL. However, the business layer was already accessing the DAL. So in reality, what is different?If you only want to expose your abstract classes then it sounds like they need to go in their own Common DAL assembly.