DbContext db = CallContext.GetData(typeof(DbContextFactory).Name) as DbContext; int id = Thread.CurrentThread.ManagedThreadId; if (db == null) { db = new Models.MyEntities(); //将新创建的 ef上下文对象 存入线程 CallContext.SetData(typeof(DbContextFactory).Name, db); } DbContext dbx = CallContext.GetData(typeof(DbContextFactory).Name) as DbContext; return db;
线程是用一个线程,db是NULL,还有个奇怪的地方是以前写的能取出来的现在取不出来了,也是null,之前是win7写的,现在换了win10,是不是有这方面的原因?。
DbContext对象好像不能跨线程传播的吧,你要么拿个对象实现ILogicalThreadAffinative接口,然后把你DbContext放进去。
最后传播的起始就是你那个包装类。
ps下,你也可以直接换用CallContext的LogicalGetData和其对应的LogicSetData来实现。
都是同一个线程的,ID一样
@cvxcrfa: 如果是同一线程,建议你debug下看下未as前取出来是什么。然后需要检查下是否有过清空数据的操作(FreeNamedDataSlot)。不管结果如何还是建议你使用Logical前缀的Get和Set,这样逻辑更严谨些。
@Daniel Cai: 访问同一个网站,会触发不同线程么?
@cvxcrfa: 当然,不然线程池里面的线程留着干嘛?
@Daniel Cai: 我理解不到位啊,请求一次他会创建一个线程,在这个线程内是取得到值得,当发起另一请求的时候,之前的线程释放了,即使是同一ID,由于之前释放了,所以为null,是不是这样?
@cvxcrfa: 是的,但你的解释不严谨。asp.net的所有请求都是依赖于线程池中的线程来处理,但并不是请求一次就会创建一个线程,是否是创建出来的依赖于你对线程池的设定及你当前线程池可用线程数。
其次由于没有看到你整体代码逻辑,所以没办法判断是不是因为线程执行完了导致你的CallContext中数据槽为空。
如果我没理解错的话,你希望是用这个factory针对同一请求在其生命周期内使用同样的dbContext对象,你这样做性能比起ThreadStatic要慢些(前提是在同一线程下)。而且如果你在处理同一请求中出现了额外的线程操作,比如你另起了一个线程做批量更新,而主处理线程去插入记录什么的。那么你的这个方法就会实例化新的dbContext出来,这个和我这段开头说的需求所抵触。
最后反推回来,你这边在第一次调用这个方法的时候第三行应该就是空,然后这边才会初始化dbcontext对象,而且这个实例化出来的对象仅在你当前线程内可见,其他同时过来的请求时看不到的(也会初始化新的dbContext)。
ps:EF中的dbContext对象的方法不是线程安全的,所以企图让所有或部分线程通过某个方式共享同一个dbContext对象进行数据操作是可能抛异常的。
看下你强转以前是不是为空
也是空的!!