Remoting技术问题,在第二次客户端激活远程组件时,前一次调用远程组件所得到的CallContext中的对像被清成掉??Why

DalyQiao 2006-10-21 12:21:14
以下是我为了在服务端和客户端中通过CallContext进行传送的类型定义
[Serializable]
public class UserToken : ILogicalThreadAffinative
{

public SqlGuid m_Session;

public UserToken(SqlGuid session)
{
m_Session = session;
}

public SqlGuid SessionId
{
get
{
return m_Session;
}
set
{
m_Session = value;
}
}

//以下两个函数是据微软的文档所说的解决方法,不过一点也没有效果,不知错在那里了.
public new int GetHashCode()
{
return base.GetHashCode();
}

public new Type GetType()
{
return base.GetType();
}
}

原先我以为CallContext中的传输的对像会一直保留,结果确不是这样.过程如下:
我设计了一个服务组件,其中一个方法会调用CallContext.SetData存入一个上述类型的对象,客户端也可以正常调用CallContext.GetData得到这个对象,然而当我再次应用客户端激活一个新的服务端对象时,CallContext中的数据确被清掉了,并得到提示"试图访问调用方不可访问的字段",为什么会这样?微软的文档说如果类型不实现ILogicalThreadAffinative接口,就不会被清掉,但不能进行远程传送,对我没什么意义.
我希望这个对像总是被传送,而不会被清掉.因为我希望它用于标识客户会话标识,表示客户是经过验证的合法客户.
...全文
262 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
股神 2006-10-22
  • 打赏
  • 举报
回复
DalyQiao 2006-10-21
  • 打赏
  • 举报
回复
找到问题了,是public SqlGuid m_Session;惹得祸,改成public string m_Session;就没事了.
怪,System.Data.SqlTypes.SqlGuid类型是支持序列化的,而且从服务端传到客户端没事,但从客户端传到服务端就有问题了(会提示那个"试图访问调用方不可访问的字段"错误,然后CallContext中的Sessionid数据项就被清掉了),不懂出了什么问题.我用的是.net 2.0版本,vs2005开发.
以下是服务端代码:
[Serializable]
public class UserToken : ILogicalThreadAffinative
{

public string m_Session;

public UserToken(SqlGuid session)
{
m_Session = session.ToString() ;
}

public SqlGuid SessionId
{
get
{
return new SqlGuid(m_Session);
}
set
{
m_Session = value.ToString();
}
}
}

//登陆的远程激活类,登陆成功后将返回一个令牌,并有意在后期也加入一个相关的客户ip地址的验证,而不止是会话标识

public class LoginVerification : MarshalByRefObject
{
public UserToken Login(string username, string pwd)
{
SqlConnection conn = DBConnString.Conn;
SqlCommand comm = new SqlCommand("bLogin", conn);
comm.CommandType = CommandType.StoredProcedure;

SqlParameter pUname = new SqlParameter( "@Uname",SqlDbType.VarChar , 50 );
pUname.Direction = ParameterDirection.Input;
pUname.Value = username;
comm.Parameters.Add(pUname);

SqlParameter pPwd = new SqlParameter("@Pwd", SqlDbType.VarChar, 1024);
pPwd.Direction = ParameterDirection.Input;
pPwd.Value = pwd;
comm.Parameters.Add(pPwd);

SqlParameter pSessionid = new SqlParameter("@Sessionid", SqlDbType.UniqueIdentifier);
pSessionid.Direction = ParameterDirection.Output;
comm.Parameters.Add(pSessionid);

try
{
comm.ExecuteNonQuery();
if (pSessionid.Value == DBNull.Value )
{
throw new Exception("用户名或密码不正确");
// return null;// new UserToken(SqlGuid.Null);
}
else
{
UserToken temp = new UserToken(new SqlGuid(pSessionid.Value.ToString()));
CallContext.LogicalSetData("Sessionid", temp);
return temp;
}
}
catch (SqlException sqlerr)
{
throw new Exception("运行时数据库出错:"+sqlerr.Message);
}
finally
{
conn.Close();
comm.Dispose();
}
}
}

客户端与服务端均很普通,没什么特别的地方.
KJ_Wang 2006-10-21
  • 打赏
  • 举报
回复
原代码全部搞出来,帮你交流,我也喜欢Remoting
winner2050 2006-10-21
  • 打赏
  • 举报
回复
帮顶

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧