none
C#程序运行时使用linq to sql 向sql server2005插入一条记录时抛出异常:“服务器无法生成类型为“Char(20)”的主键列。” RRS feed

  • 问题

  • 本人使用.net 2008
    数据库中有一个T_Users表,其中 userid char(20) not null  为主键列,在.net程序中使用
    linq to sql 想往数据库中插入一条记录时发生的错误,
    背景资料:开发一个通用的权限管理模块,使用PowerDesigner 生成了物理模型,使用sql query语句在 sql server2005中生成了十几个表,其中有一个用户表

    /*系统用户信息表:T_Users*/
    create table T_Users (
       UserID               char(20)             not null,
       UserName             Z_Name               not null,
       UserPWD              char(32)             null,
       UserState            int   default 1      not null,/*0:禁止,1:正常*/
       CreateTime           Z_DateTime    default getdate()       not null,
       constraint PK_T_USERS primary key nonclustered (UserID)
    )
    在 .net 中使用c# 的 LINQ to SQL 自动生成了表的实体类和 DataContext 类,在中间层写了一个类来调用DataContext 类来连接和操作数据库

    使用一个测试程序test来调试中间类的方法,当往数据库中插入一条用户记录时,运行到SubmitChanges()抛出异常错误

    执行的代码如下整理后如下:
            T_Users uu;
                uu=new T_Users()
                {
                UserID=textBox1.Text.Trim(),//="liu"
                UserName = textBox2.Text, //="test"
                UserPWD = textBox4.Text,//="123456"
                UserState=1 ,
                CreateTime=System.DateTime.Today};


            pmdc.T_Users.InsertOnSubmit(uu);
                   
              pmdc.SubmitChanges();

    (其中pmdc为DataContext对象)
    上面执行第3行 的pmdc.SubmitChange()时发生错误,错误详细信息如下,请高手帮忙解决 显示消息为“服务器无法生成类型为“Char(20)”的主键列。”下面是复制到剪贴板的详细信息:

    未处理 System.NotSupportedException
      Message="服务器无法生成类型为“Char(20)”的主键列。 "
      Source="System.Data.Linq"
      StackTrace:
           在 System.Data.Linq.SqlClient.QueryConverter.GetIdentityExpression(MetaDataMember id, Boolean isOutputFromInsert)
           在 System.Data.Linq.SqlClient.QueryConverter.VisitInsert(Expression item, LambdaExpression resultSelector)
           在 System.Data.Linq.SqlClient.QueryConverter.VisitDataManipulationCall(MethodCallExpression mc)
           在 System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
           在 System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node)
           在 System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations)
           在 System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
           在 System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject item)
           在 System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject item)
           在 System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
           在 System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
           在 Zetasoft.Permission.ZetaPermissionController.InsertAUser(T_Users user, String& ErrString) 位置 D:\dotnetWork\Zeta.敏捷软件工厂\Zetasoft\Zetasoft\ZetaPermissionController.cs:行号 168
           在 test.Form1.button2_Click(Object sender, EventArgs e) 位置 D:\dotnetWork\Zeta.敏捷软件工厂\Zetasoft\test\Form1.cs:行号 76
           在 System.Windows.Forms.Control.OnClick(EventArgs e)
           在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
           在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
           在 System.Windows.Forms.Control.WndProc(Message& m)
           在 System.Windows.Forms.ButtonBase.WndProc(Message& m)
           在 System.Windows.Forms.Button.WndProc(Message& m)
           在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
           在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
           在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
           在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
           在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
           在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
           在 test.Program.Main() 位置 D:\dotnetWork\Zeta.敏捷软件工厂\Zetasoft\test\Program.cs:行号 18
           在 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
           在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           在 System.Threading.ThreadHelper.ThreadStart()
      InnerException:
    请论坛里的高手、高高手和大虾们帮忙诊断下,看是什么原因造成的?个人推断的思路:
    是不是和 表的主键 userid 有关,因为主键是Char(20)长度的!在建立linq to sql到数据库表的映射时生成的自动代码(表的实体类和DataContext类)是不是需要在某个地方修改某个属性
    以匹配sql 数据库的规范?

    下面是linq to sql 自动生成的实体类userid的映射:

      [Column(Storage="_UserID", AutoSync=AutoSync.OnInsert, DbType="Char(20) NOT NULL", CanBeNull=false, IsPrimaryKey=true, IsVersion=true)]
      [DataMember(Order=1)]
      public string UserID
      {
       get
       {
        return this._UserID;
       }
       set
       {
        if ((this._UserID != value))
        {
         this.OnUserIDChanging(value);
         this.SendPropertyChanging();
         this._UserID = value;
         this.SendPropertyChanged("UserID");
         this.OnUserIDChanged();
        }
       }
      } 

     

     

    2010年8月27日 14:27

答案

  • 你那个userid 无法由数据库自动生成而已。  把实体类主键属性上加个 [Column(IsPrimaryKey = true, IsDbGenerated = false)]

    插入的时候在程序中给主键赋值,并检查重复。。。

    如果想在数据库端生成,必须写个函数产生不可重复的userid. 然后将函数作为字段默认值。

    • 已标记为答案 Mog Liang 2010年9月3日 8:52
    2010年9月1日 10:11

全部回复

  • 你那个userid 无法由数据库自动生成而已。  把实体类主键属性上加个 [Column(IsPrimaryKey = true, IsDbGenerated = false)]

    插入的时候在程序中给主键赋值,并检查重复。。。

    如果想在数据库端生成,必须写个函数产生不可重复的userid. 然后将函数作为字段默认值。

    • 已标记为答案 Mog Liang 2010年9月3日 8:52
    2010年9月1日 10:11
  • 数据库端设计成 char(20)的主键,但是我在客户端是显式提供了它的唯一值啊!按道理数据库就应该用我提供的值插入啊
    “这不是我的错”,这句话不对。“这都是你的错”,这句话更不对。如果你没有犯过任何错误,就说明你可能没有努力去工作。
    2010年9月7日 7:02