I have structured a project with a single LINQ to SQL .dbml file and a single DataAccess class that is used to call stored procs and query against this this DBML class. The DataAccess class implements the singleton pattern inasmuch as their's a static DataAccess property which is used for all DB access.
The business layer of the application creates an instance of the DataAccess object, calls the appropriate data access function and then returns.
When running as a web application it is being hit rapidly by 2 clients: (1) a browser calls to it about 1 to 50 times a second (writes data to DB) and (2) an excel spreadsheet calls the web app via a web service on an ad hoc basis and does a query for data.
When the spreadsheet does the query (the browser's hitting the site up to 50 times a second at the same time) I am getting several errors such as the following:
- Invalid attempt to call MetaData when reader is closed
- There is already an open DataReader associated with this Command which must be closed first.
- ExecuteNonQuery requires an open and available Connection. The connection's current state is closed.
- A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 18 - Connection has been closed by peer)
- A severe error occurred on the current command. The results, if any, should be discarded.
- A transport-level error has occurred when receiving results from the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)
The first 2 errors were solved by adding MARS to the connection string: MultipleActiveResultSets=true
The rest of them I solved by adding a static lock object to the DataAccess class and wrapping all calls to the database in a lock(lockObj) {}.
This solution doesn't feel right though.
Comments on the general approach I've taken... Comments on the lock() solution...