Question

This works, but Resharper says, "Access to disposed closure" on the commented line

using (var db = new SQLiteConnection(SQLitePath))
            {
                db.CreateTable<Locations>();

                db.RunInTransaction(() =>
                {
                    db.Insert(new Locations // Resharper: "Access to disposed closure" ???
                    {
                        PersonId = personId,
                        Latitude = latitude,
                        Longitude = longitude,
                        SentTimeUTC = sentTimeUTC,
                        ReceivedTimeLocal = receivedTimeLocal,
                        CivicAddress = civicAddress
                    });
                });
            }

This alternate approach also works, but with the same fingerwag from Resharper:

    var db = new SQLiteConnection(SQLitePath);
    {
        db.CreateTable<Locations>();

        db.RunInTransaction(() =>
        {
            db.Insert(new Locations // this works, although Resharper warns: "Access to disposed closure" ???
               {
                   PersonId = personId,
                      Latitude = latitude,
                      Longitude = longitude,
                      SentTimeUTC = sentTimeUTC,
                      ReceivedTimeLocal = ReceivedTimeLocal,
                      CivicAddress = civicAddress
               });
        });
    }
    db.Dispose();

They both work, so I guess it doesn't matter too much, but is one way preferable to the other? Is there a way to mollify Resharper and still get the job done?

UPDATE

What Donal said seemed sensible, yet I still get the Resharper "Potential Code Quality Issue" warning with this refactored code, on the Insert statement within the xaction:

public void InsertLocationRecord(string personId, double latitude, double longitude,
    DateTime sentTimeUTC, DateTime receivedTimeLocal, string civicAddress) 
{
    Locations locs = new Locations { PersonId = personId,
                                     Latitude = latitude,
                                     Longitude = longitude,
                                     SentTimeUTC = sentTimeUTC,
                                     ReceivedTimeLocal = receivedTimeLocal,
                                     CivicAddress = civicAddress
                                   };

    using (var db = new SQLiteConnection(SQLitePath))
    {
        db.CreateTable<Locations>();

        db.RunInTransaction(() =>
                                {
                                    db.Insert(locs); // Still get, "Access to disposed closure" on this line.
                                });
    }
}

Maybe I'm refactoring the problem in the wrong way? I guess this is not really much different than the previous way; how do I assure that the locs instance is disposed? Or is that not the issue here?

Was it helpful?

Solution

The problem is that you are creating a custom subclass of Locations in the middle there, which picks up all sorts of things that it doesn't need as part of the current context, and ReSharper is picking up on that (and isn't able to prove that it doesn't escape somehow). The easiest way to fix would actually be to add a constructor (or constructors, if necessary) to Locations to allow you to instantiate it with all the right values without closure capture.

OTHER TIPS

Step 1: Assuming you have code in your Location class like so.

class Locations { 
    int PersonId;
    int Latitude;
    int Longitude;
    int SentTimeUTC;
    int ReceivedTimeLocal;
    int CivicAddress;

    // Functions;

    // {
    // Disposable resource
    // }
    public Locations (latitude,longitude,sentTimeUTC,receivedTimeLocal,civicAddress)
    {
        PersonId = personId;
        Latitude = latitude;
        Longitude = longitude;
        SentTimeUTC = sentTimeUTC;
        ReceivedTimeLocal = receivedTimeLocal;
        CivicAddress = civicAddress;
    };
};

Change your class to an IDisposable class like so.

class Locations : IDisposable { 
    int PersonId;
    int Latitude;
    int Longitude;
    int SentTimeUTC;
    int ReceivedTimeLocal;
    int CivicAddress;

    // Functions;

    // {
    // Disposable resource
    // }
    public Locations (latitude,longitude,sentTimeUTC,receivedTimeLocal,civicAddress)
    {
        PersonId = personId;
        Latitude = latitude;
        Longitude = longitude;
        SentTimeUTC = sentTimeUTC;
        ReceivedTimeLocal = receivedTimeLocal;
        CivicAddress = civicAddress;
    }

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) {
        if (disposing) {
            // Free your disposable resources here
            base.Dispose(disposing);
        }
    }
};

Step 2: Then change your call to the original code

Locations locs = new Locations { PersonId = personId,
         Latitude = latitude,
         Longitude = longitude,
         SentTimeUTC = sentTimeUTC,
         ReceivedTimeLocal = receivedTimeLocal,
         CivicAddress = civicAddress
       };
using (var db = new SQLiteConnection(SQLitePath))
{
db.CreateTable<Locations>();

db.RunInTransaction(() =>
    {
        db.Insert(locs); // Still get, "Access to disposed closure" on this line.
    });
}

to

using (Locations locs = new Locations { PersonId = personId,
         Latitude = latitude,
         Longitude = longitude,
         SentTimeUTC = sentTimeUTC,
         ReceivedTimeLocal = receivedTimeLocal,
         CivicAddress = civicAddress
    }) {
    using (var db = new SQLiteConnection(SQLitePath))
    {
    db.CreateTable<Locations>();

    db.RunInTransaction(() =>
        {
            db.Insert(locs); // Still get, "Access to disposed closure" on this line.
        });
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top