Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The answer, for me, was related to one of the links I posted.</p> <p><a href="https://stackoverflow.com/questions/2030665/how-do-i-share-a-data-context-across-various-model-repositories-in-asp-net-mvc-u"> how do I share a data context across various model repositories in asp.net</a></p> <p>What threw me off when I saw these types of injection answers was that syntactically they didn't work for me. I don't have DataContext nor do I have any Repository models, but I decided to give it a try conceptually and pass the Context around everywhere.</p> <p>Basically, I passed in the connection to the Object constructor or to any factory methods where a new object is created and store that in a local variable, sorta like this.</p> <pre><code>public class Foo{ private MyDB _db; private Foo _foo; public FooObject(MyDB dbContext) { _db = dbContext; } public static FooObject GetFooObject(int FooID, MyDB db){ bool closeFlag = false; //if null was passed in, then we will create our own connection and manage it if (db == null) { _db = new MyDB(); closeFlag = true; } else { //otherwise, we set our local variable _db = db; } //from now on, all queries are done using the local variable var _f = _db.Foos .Include("x") .Include("y") .Include("z") .SingleOrDefault(f =&gt; f.FooID == FooID); var fo = FooObjectFromFoo(_f, db); if (closeFlag) db.Dispose(); return fo; } // This copies all of the values from Foo and puts the into a FooObject public static FooObject FooObjectFromFoo(Foo f, MyDB dbContext){ if (l == null) return null; // note that we pass the dbContext to the constuctor FooObject _f = new FooObject(dbContext){ _foo = f, ... //note x, y, and z are the other EF "table references". I'm not sure what you technically call them. x = f.x, y = f.y, z = f.z }; return _f; } //we call this to save the changes when we're done public bool Save(){ bool close = false; bool retval = true; MyDB db = _db; //remember we set _db in the constructor if (db == null) { db = new MyDB(); close = true; } try { // a reference to this row should have been saved in _foo if we loaded it from the db. // take a look at FooObjectFromFoo if (_foo == null) { _foo = db.Foos.SingleOrDefault(x =&gt; x.FooID == _FooID); } if (_foo == null) { _foo = new Foo(); } //copy all my object values back to the EF Object _foo.blah = blah; _foo.x = x; _foo.y = y; try { //save the new one. db.SaveChanges(); } catch (DbEntityValidationException dbEx) { TransactionResult.AddErrors(dbEx); retval = false; } } catch { throw new Exception("Something went wrong here.");} finally { if (close) db.Dispose(); } //if we created this connection then let's close it up. } } </code></pre> <p>And now in my methods, I always use the local _db connection. Outside of my FooObject we have a FooService which is what is called from all of the controllers. So when FooService is instantiated I create a db connection using my class below. If I understand it properly, this should give me a context that exists for the duration of my service request which, in my case, fairly reliably mimics the request.</p> <pre><code>namespace My.Domain { public class MyDataContext : IDisposable { private MyDB _context; private bool _ownContext; public MyDataContext(){ _context = new MyDB(); _ownContext = true; } public MyDataContext(MyDB db) { _context = db; _ownContext = false; } public MyDB Context { get { if (_context == null) { _context = new MyDB(); _ownContext = true; } return _context; } set { _context = value; } } public bool OwnContext { get { return _ownContext; } set { _ownContext = value; } } public void Dispose() { if (_context != null &amp;&amp; _ownContext) _context.Dispose(); } } } </code></pre> <p>In the FooService I do stuff like this.</p> <pre><code> private MyDb db; public FooService (){ var _db = new MyDataContext(); db = _db.Context; } public Result ProcessTransaction(int FooId, string comment) { var foo = FooObject.GetFooObject(FooId,db); Result r = foo.ProcessTransaction(comment); if (r.Success) foo.Save(); return r; } </code></pre> <p>I think to do it "right" I should only save the changes when I close out the context... but I already had a Save method on my FooObject, so I just call db.SaveChanges in there.</p> <p>I know there are lots of ways to improve this and I'm sure I'll implement some of them over time, but for now, this did the trick. This was how I got around all of the "Context is no longer available" and this object was from a different context errors.</p> <p>The thing that tripped me up when looking at other peoples examples is they were all using CodeFirst and dependency injection of some sort. They commonly used Repository patterns and we don't have any of that. But it turns out that I just had to implment my own hacked-up localized version of connection injection! :)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload