NBearV3 Step by Step教程——ORM篇

版本

1.7 [2006-1-16]

简介

本教程演示如何基于NBearV3ORM模块开发一个Web应用程序的全过程。本教程演示的实体关系包括:继承、11关联、1对多关联,多对多关联。同时,本教程还演示如何设计实体属性为nullable类型或符合类型。

注:所谓nullable类型主要是针对之类型而言的,.Net2.0位所有的值类型支持nullable,设为nullable的值类型,允许是null的,这样,就可以映射数据库中的null;而符合类型指这个属性是一个复合类型,但是,保存到数据库的时候,整个复合类型序列化后保存为一个数据表的字段的值。

目标

通过本教程,读者应能够掌握使用NBearV3ORM模块进行应用程序设计的基本过程,以及开发过程中,NBearV3提供的相关工具的使用方法。

代码

本教程演示创建的所有工程和代码,包含于可以从sf.net下载的NBearV3最新源码zip包中的tutorials\ORM_Tutorial目录中。因此,在使用本教程的过程中如有任何疑问,可以直接参考这些代码。

时间

<45分钟。

正文

Step 1 下载NBearV3最新版本

1.1访问http://sf.net/projects/nbear,下载NBearV3的最新版本到本地目录。

1.2 将下载的zip文件解压至C:\,您将看到,加压后的NBearV3目录中包括:distdoccasessrc等目录。其中,在本教程中将会使用的是dist目录,该目录下包含所有release编译版本的dllexe

Step 2 创建应用程序解决方案

2.1 打开VS2005开发环境,新建一个空的解决方案sln

2.2 sln中添加两个新建的C#类库工程,两个类库工程的名称分别为EntityDesignsEntities,删除IDE自动创建的Class1.cs文件。

2.3 sln中新建一个名叫websiteASP.NET Web应用程序,为website添加一个Web.config文件。

Step 3 设计实体及关系

3.1 2.2创建的EntityDesigns工程中,新建一个名为ClassDiagram.cd的类图文件。注:如果您的IDE不支持类图设计,或者您更习惯写代码,您也可以参照下面的步骤直接创建代码。

3.2EntityDesigns工程添加到dist目录下的NBear.Common.Design.dll的引用。因为下面的每一个设计实体接口必须继承自NBear.Common.Design.Entity这个接口。在Entities工程中创建一个名为UserNamestruct包含FirstNameLastName两个string类型的Field。同时在Entities工程中创建一个名为UserStatus的枚举类型,包含两个枚举选项:AvailaleDeleted。注:这两个类型将用于后面的设计实体的设计。之所以这两个类型定义在Entities工程中而不是EntityDesigns工程中是,最终,所有生成的实体将放在Entities工程,且Entities工程最后对EntityDesigns工程是没有依赖关系的。

3.3 双击ClassDiagram.cd打开设计界面,您现在就可以设计实体了。注意,所有的设计实体必须是接口。为了使用3.2创建的类型,需要让EntitDesigns工程引用Entities工程。

3.4 向类图中添加一个User接口,继承自NBear.Common.Design.Entity。添加属性IDNameStatusBirthday。类型分别为GuidUserNameUserStatusDateTime?。注意,这里的NameStatus的类型为3.2创建的自定义符合类型UserName和枚举类型UserStatus。而Birthday属性的类型为一个Nullable类型的DateTime?。注意DateTime后面的问号,表示这个类型实际是一个Nullable<DateTime>,也就是说,Birthday类型如果不赋初始值的话,它的值为null

3.5 向类图中再添加一个LocalUser接口,继承自NBear.Common.Design.Entity。添加属性LoginNamePassword。类型都为string

3.6 从工具栏添加继承线条,让LocalUser继承User

3.7 向类图中添加一个UserProfile接口,继承自NBear.Common.Design.Entity。添加属性IDUserIDProfileContent。类型分别为GuidGuidstring。注:这里的ProfileContent仅仅象征型的代表profile数据,用于演示11关联,实际的项目中可能会有更多属性。

3.8 从工具栏添加关联线条,让User包含一个名叫Profile的UserProfile类型的属性。这样我们就1对1关联了User和UserProfile实体。注:如果操作图形设计界面觉得麻烦,也可以切换到源代码界面,直接编码。

3.9 向类图中添加一个LocalUserPhone接口,继承自NBear.Common.Design.Entity。添加属性IDUserIDDescriptionNumber。类型分别为GuidGuidstringstring

3.10 从工具栏添加关联线条,让LocalUser包含一个名叫Phones的类型为LocalUserPhone[]的数组类型的属性。这样我们就1对多关联了LocalUser和UserPhone。

3.11 向类图添加一个Group接口,继承自NBear.Common.Design.Entity。添加属性IDName。类型分别为Guidstring

3.12 从工具栏添加关联线条,让User包含一个名叫Groups的类型为Group[]的数组类型的属性。注意,这里我们要实现的是多对多关联,所以下面我们还要建一个UserGroup关联实体来连接这个多对多关系。

3.13 向类图添加一个UserGroup接口,继承自NBear.Common.Design.Entity。添加属性UserIDGroupID。类型都是Guid

设计完的实体关系图,应该类似下面这样:



Step 4 设置设计实体元数据

4.1 切换到源代码视图。首先,我们要为除了关联实体UserGroup之外(对于关联实体,凡是标记为RelationKey的属性,会被自动认为是复合主键)的所有设计实体的主键设置PrimaryKey这个Attribute,可以为多主键实体的每个主键添加该属性。如果不正确设置主键,代码生成工具将不能正确生成数据库创建脚本。例如,对于User实体的ID属性,设置后的代码象下面这样:

        [PrimaryKey]
        Guid ID
        
{
            
get;
            
set;
        }

注:大家可能有疑问,为什么这里主键ID能不能是int,并且是自增长的只读属性呢?答案是完全可以的,完全可以设置某个ID属性为下面这样,无需额外设置,它将映射到一个自增长只读的int类型的数据库字段:

        [PrimaryKey]
        
int ID
        
{
            
get;
        }

4.2 在后面的步骤生成实体对应的数据库创建脚本时,对于数值类型,nullable类型和枚举类型,NBear能够自动将他们对应到数据库的对应类型,但是,对string类型,一般需要指定其映射到数据库时的具体类型和长度。当然,也可以不指定,如果不指定,则string类型默认被映射为nvarchar(127)。例如,对于UserProfile的ProfileContent属性,我们添加下面的Attribute,设置其映射到数据库的类型为ntext:

        [SqlType("ntext")]
        
string ProfileContent
        
{
            
get;
            
set;
        }

又如,对于LocalUserPhoneNumber属性,我们添加下面的Attribute,设置其映射到数据库的类型为nvarchar(20)

        [SqlType("nvarchar(20)")]
        
string Number
        
{
            
get;
            
set;
        }

4.2 对于User的Name这个UserName类型的复合类型,我们也需要设置其SqlType,一般设为ntext,因为,默认情况下复合类型被序列化为XML,并保存于对应的数据库字段。另外,复合类型还必须使用CompoundUnit这个Attribute标记,所以User的Name属性需要被设置成下面这样:

        [CompoundUnit]
        [SqlType(
"ntext")]
        UserName Name
        
{
            
get;
            
set;
        }

注:继承关系不需要特别设置NBear可以识别接口的自然继承关系,但是,注意,不要让一个设计实体接口继承超过一个基类接口,否则,NBear将不能识别这种继承关系。换句话说,NBear不支持多根继承。之所以有这个限制是因为,后面,所有这些设计实体接口会被自动生成为class形式的实体代码,而class是不支持多根继承的。

4.3 对于User和UserProfile的1对1关联,我们需要为User接口的Profile属性设置下面的Attributes(这些Attribues都包含于NBear.Common.Design中,因此,需要注意在代码中using NBear.Common.Design):

        [FkQuery("UserID", Contained = true, LazyLoad = false)]
        UserProfile Profile
        
{
            
get;
            
set;
        }

其中,FkQuery代表这个属性是一个1对1外键关联,参数UserID表示,在UserProfile实体中,UserID为对应的外键。LazyLoad=false容易理解,表示这个属性不是知道访问才载入数据的,而是,在实例化User对象的时候,就自动载入Profile属性的数据。当然,如果需要,也可以将LazyLoad设为true。另外,可以像下面这样设置UserProfile的UserID属性为外键,则生成的数据库脚本将包含外键引用完整性检测:

        [FriendKey(typeof(User))]
        Guid UserID
        
{
            
get;
            
set;
        }

4.4 对于LocalUser和LocalUserPhone的1对多关联,我们需要为LocalUser接口的Phones属性设置下面对的Attributes

        [FkQuery("UserID", Contained=true, LazyLoad=true)]
        LocalUserPhone[] Phones
        
{
            
get;
            
set;
        }


这里
LocalUserLocalUserPhones1对多外键关联。Contained=true表示Phones跟随LocalUser级联更新。

4.5 对于User和Group的多对多关联,我们为User.Groups属性设置下面的Attributes

        [ManyToManyQuery(typeof(UserGroup), OrderBy="{Name} DESC", LazyLoad=true)]
        Group[] Groups
        
{
            
get;
            
set;
        }

我们可以看到,和前面的1对1和1对多关联相比,多对多关联的主要区别是必须设置ManyToManyQuery的构造函数参数,指定关联实体为UserGroup。这里的OrderBy并不是必须的,如果不指定,则载入的Group按默认规则排序。

4.6 另外,还需要设置UserGroup这个关联实体的属性如何与UserGroup的属性进行关联。我们需要对UserGroup这个实体关联接口及它的属性设定下面的Attributes

    [Relation]
    
public interface UserGroup : NBear.Common.Design.Entity
    
{
        [RelationKey(
typeof(User))]
        Guid
 UserID
        
{
            
get;
            
set;
        }


        [RelationKey(
typeof(Group))]
        Guid GroupID
        
{
            
get;
            
set;
        }

    }

 注意,首先,关联实体必须使用Relation这个Attribute修饰。其次,每一个关联属性的用于关联的属性,必须使用RelationKey这个Attribute修饰。RelationKey的唯一参数指定这个属性关联到哪一个实体。例如,这里,UserGroup的UserID属性关联到User实体;而GroupID属性则关联到Group实体。

4.7 对于LocalUserPassword,我们可以添加NotNullSerializationIgnore这两个Attribute,显式地设置其对应字段为非空,并且,保证其不会被包含在默认的XML序列化中。设置到设计实体的SerializationIgnore,会在最终生成的实体中用XmlIngore标识。

        [SqlType("nvarchar(50)")]
        [NotNull]
        [SerializationIgnore]
        
string Password
        
{
            
get;
            
set;
        }

Step 5 从实体设计代码生成实体代码、实体配置文件和数据库生成脚本

5.1 至此,所有的实体的设计就完毕了。编译EntityDesigns工程。

5.2 运行dist目录中的NBear.Tools.EntityDesignToEntity.exe工具,载入EntityDesigns工程编译生成的EntityDesigns.dll

5.3 点击Generate Entities按钮,将生成的代码保存到Entities工程中的一个名叫Entities.cs的新代码文件。并为Entities工程添加到dist\NBear.Common.dll的引用。

5.4 点击Generate Configuration按钮,将生成的代码保存到website工程下的名为EntityConfig.xml的新文件中。

5.5 点击Generate DB Script按钮,将生成的代码保存到website工程下的名为db.sql的新文件,可以在某个新建的SQL Server数据库中执行这些脚本,创建对应于所有实体的数据库脚本。

Step 6 使用实体及NBear.Data.Gateway访问数据库

6.1 现在我们就可以使用前面生成的实体了。我们先要让website工程引用Entities工程,以及dist/NBear.Data.dll

6.2 我们还需要设置websiteWeb.config文件,添加一个entityConfig section以包含EntityConfig.xml这个实体配置文件,并设置数据库连接字串。下面是设置完的Web.config,注意,粗体的部分都是我们添加的代码(注意,这里的connectionstring连接到SQL Server数据库的tempdb数据库,我们需要对tempdb数据库执行5.5生成的数据库创建脚本,另外也注意修改数据库登录密码。):

<?xml version="1.0"?>
<configuration>
 
<configSections>
    
<section name="entityConfig" type="NBear.Common.EntityConfigurationSection, NBear.Common" />
 
</configSections>
 
<entityConfig>
    
<includes>
      
<add key="Sample Entity Config" value="~/EntityConfig.xml" />
    
</includes>
 
</entityConfig>
 
<appSettings/>
 
<connectionStrings>
    
<add name="DbName" connectionString="Server=(local);Database=tempdb;Uid=sa;Pwd=sa" providerName="NBear.Data.SqlServer.SqlDbProvider"/>
 
</connectionStrings>
 
<system.web>
        
<compilation debug="false" />
        
<authentication mode="Windows" /
    </system.web
>
</configuration>

6.3 好了,现在,我们就可以随心所欲的访问数据库了。将下面的代码添加至website工程的Default.aspx.cs文件(您也可以直接打开tutorials\ ORM_Tutorial\website目录下的Default.aspx.cs,从那里复制代码)。这些代码演示了一个非常典型的创建和级联更新有复杂关系的实体的过程,并伴有详细解说。关于Gateway支持的更多方法的介绍,可以参考doc目录下的SDK类库文档。

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using Entities;
using NBear.Common;
using NBear.Data;

public partial class _Default : System.Web.UI.Page 
{
    
protected void Page_Load(object sender, EventArgs e)
    
{
        
//init a Gateway, the param "tempdb" is the connectionstring name set in Web.config
        Gateway gateway = new Gateway("tempdb");    //youcan also use gateway = Gateway.Default, which maps to the last connectionstring in Web.config

        
create & save a LocalUser

        
Check saving result
    }


    
private void WriteLine(string str)
    
{
        Response.Write(Server.HtmlEncode(str) 
+ "<br /><br />");
    }


    
private string CustomSerializeUserName(object name)
    
{
        UserName userName 
= (UserName)name;
        
return userName.FirstName + "," + userName.LastName;
    }


    
private object CustomDeserializeUserName(string data)
    
{
        
string[] splittedData = data.Split(',');
        UserName userName 
= new UserName();
        userName.FirstName 
= splittedData[0];
        userName.LastName 
= splittedData[1];
        
return userName;
    }

}

6.4 运行以上代码,您将得到类似到下面的结果:

Create a new local user and set property values.
Create & set the user name.
Create & set the local user phones
Create & set the user groups.
Save the new local user.

After we saved the local user.
We found the saved local user itself.
We found the saved local user itself as a user.
We found the 1 to 1 related user profile of the saved local user was also saved.
Oh! many to many related local user group of the saved local user was NOT saved!! Do you know why? - It is NOT because it is many to many related while profile and phones are 1 to 1 or 1 to many. It is not because your are not Teddy, either. :) It IS because in the entity design of User, the Groups property is NOT marked with the [Contained] attribute.
To save an uncontained property value, such as user's Groups, you have to manually do this.
Firstly, you should save the group it self.
Furthermore, you have to create & save a usergroup relation entity manually. Let's do it.
Let's find the saved local user again. Was the group saved this time?
Yes, conguratulation! This time, we found the many to many related local user group of the saved local user was finally saved.
Do you want to know the saved user name's details, which is a compoundunit property? Ok, show you what you want, in fact, it is serialized as xml by the NBear.Common.SerializationManager class, looks like:
<?xml version="1.0" encoding="utf-16"?> <UserName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <FirstName>teddy</FirstName> <LastName>ma</LastName> </UserName>
Ok, I heard you considering whether you can save it into some other format because you do not want it to be XML? You do have chance to control this!!
What youshould do is easily register a custom serialize/deserialize delegate method pair.
Let's save the user name again.
What does the details of the user name now become? It becomes:
teddy,ma
Cool!~~ Right? But remember, in real project, you must register the custom serialize/deserialize delegate method pair at application started up. For example, in Application_Start().
Thank you so much for having completed this tutorial. You can look up the appendixes, for more information about the usage of the Gateway.
See you later!
Warm regards,
Teddy 2006-11-3

正文结束。

附录

1 关于ConnectionStrings的设置

这里定义了五个ConnectionString,分别对应MS AccessMS SQL ServerSQL Server 2005MySqlOracle数据库。

<connectionStrings>
   
<add name="TestAccessDb" connectionString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Teddy\NBear\skeleton\Simple\website\App_Data\TestAccessDb.mdb" providerName="NBear.Data.MsAccess.AccessDbProvider"/>
   
<add name="Northwind" connectionString="Server=(local);Database=Northwind;Uid=sa;Pwd=sa" providerName="NBear.Data.SqlServer.SqlDbProvider"/>
   
<add name="Northwind2" connectionString="Server=(local);Database=Northwind;Uid=sa;Pwd=sa" providerName="NBear.Data.SqlServer9.SqlDbProvider9"/>
   
<add name="MySql" connectionString="Dsn=mysqltest;database=test;option=3;server=localhost;uid=root;password=sa" providerName="NBear.Data.MySql.MySqlDbProvider"/>
   
<add name="Oracle" connectionString="Data Source=localhost;User ID=system;Password=sa;Unicode=True" providerName="NBear.Data.Oracle.OracleDbProvider"/>
</connectionStrings>

2 关于Gateway的初始化和连接多数据库

 

除了使用Gateway.Default之外,还可以下面两种方式实例化Gateway

1)使用配置文件中的ConnectionStringname属性对应的名称来初始化Gateway。例如,

public static Gateway Northwind = new Gateway("Northwind");
public static Gateway TestAccessDb = new Gateway("TestAccessDb");

我们可以像这样实例化多个Gateway对应不同的ConnectionString

2)如果您不将ConnectionString定义于应用程序的配置文件中,那么,就需要直接提供ConnectionString来初始化了。下面是几个典型的初始化示例:

Gateway TestDbAccess = new Gateway(DatabaseType.MsAccess, @"C:\Teddy\NBear\skeleton\Simple\website\App_Data\TestAccessDb.mdb");
Gateway Northwind 
= new Gateway(DatabaseType.SqlServer, @"Server=(local);Database=Northwind;Uid=sa;Pwd=sa");
Gateway Northwind2 
= new Gateway(DatabaseType.SqlServer9, @"Server=(local)\SQLEXPRESS;Database=Northwind;Uid=sa;Pwd=sa");
Gateway.Default 
= new Gateway(DatabaseType.MySql, "Dsn=mysqltest;database=test;option=3;server=localhost;uid=root;password=sa");
Gateway.Default 
= new Gateway(DatabaseType.Oracle, "Data Source=localhost;User ID=system;Password=sa;Unicode=True");

注意以上的代码使用了Gateway构造函数的另一个重载版本,接受一个DatabaseType参数和一个ConnectionString。这五行示例分别实例化了对应于MSAccessMS SQL Server 2000MS SQL Server 2005MySqlOracle的数据库的Gateway

//本文结束。

0
0
(请您对文章做出评价)
« 上一篇:发布NBearV3.0.5 beta包括SDK文档
» 下一篇:NBearV3 Step by Step教程——ORM进阶篇
posted @ 2006-11-03 14:57 Teddy's Knowledge Base 阅读(18959) 评论(99)  编辑 收藏 网摘 所属分类: NBear

  回复  引用  查看    
#1楼2006-11-03 15:00 | stonezhu      
顶一个,有机会用用你的框架,N人:)
  回复  引用  查看    
#2楼2006-11-03 15:27 | aspnetx      
支持,支持
期待更多的教程发布

  回复  引用    
#3楼2006-11-03 15:30 | debug[未注册用户]
坐沙发先,再仔细看!
  回复  引用  查看    
#4楼2006-11-03 15:33 | Jason Cui      
居然已经3.0了,强。
这种带关系的映射,比较注重的一点是,如果我设了Lazy=false,是不是可以用一条Sql语句取出数据?如果跟lazy=true一样需要多条语句来读,那意义也不大。或者,如果我加了两个表之间的映射,是不是可以做更好的表缓存?
这些在NHibernate里面似乎都是有处理的。

  回复  引用    
#5楼2006-11-03 15:35 | 随风.NET[未注册用户]
精力真是旺盛
  回复  引用    
#6楼2006-11-03 15:51 | lvchaoin[匿名][未注册用户]
是否可以像[SqlType("nvarchar(20)")],再加入一个[SqlDefaultValue("newid()")]类似的属性以支持数据库默认值的设置,或者给SqlType属性再加入一个参数达到目的呢?代码还没看太明白,请指导,谢谢:)

  回复  引用  查看    
#7楼2006-11-03 16:05 | Jason Cui      
对了,自关联怎么做?
  回复  引用    
#8楼2006-11-03 16:54 | 小宝[匿名][未注册用户]
终于有教程了
  回复  引用  查看    
#9楼[楼主]2006-11-03 17:16 | Teddy's Knowledge Base      
@Jason Cui
缓存方案正式版肯定会有的,现在还在思考和选择中。

关于查询优化,我还会加强,包括一次多取一些数据回来,减少数据库读写等,虽有这不是每个数据库都支持,但是像sql server或oracle这样的数据库,能优化,就应该努力优化的。当然会保持现在的接口不变。

自关联对于1对1和1对多的情形,现在的方案应该就能和非自关联一样处理,但是对于多对多,现在还不支持自关联。另外请大家注意不要讲太多的属性设为lazyload=false,以避免循环载入。我在后面的版本会加入循环载入的检测,现在还没检测,只有大家先小心。

@lvchaoin[匿名]
谢谢你的建议,我在下一版会添加默认值支持。


  回复  引用    
#10楼2006-11-03 17:39 | 忘情水[未注册用户]
强烈关注跟支持中!
  回复  引用    
#11楼2006-11-03 17:56 | 稻草人[匿名][未注册用户]
Teddy,早上看你邮件的回得说要做V3的教程,下午你就弄出来了,老兄你速度真快啊,大家要支持啊,。。。。。
  回复  引用    
#12楼2006-11-03 17:57 | 小宝[匿名][未注册用户]
我按教程做到向类图中添加一个User接口,但出现'未能创建namespace"EntityDesigns"'错误
  回复  引用    
#13楼2006-11-03 19:05 | 小宝[匿名][未注册用户]
自己解决了,原来要先新建一个名为User.cs接口的代码文件才能在类设计器中拉一个User接口进类图
  回复  引用    
#14楼2006-11-03 19:23 | aysun168[未注册用户]
顶一下
  回复  引用  查看    
#15楼2006-11-03 21:27 | Jason Cui      
老兄给个自关联的代码吧,我想像不出来。
  回复  引用  查看    
#16楼[楼主]2006-11-04 07:33 | Teddy's Knowledge Base      
@Jason Cui
例如,如果一个Person有一个FamilyID,FamilyID相同的人属于一家人。可以这样定义这个1对多关联:
public interface Person : Entity
{
   int ID { get; set; }
   string Name { get; set; }
   int FamilyID { get; set; }

   //其他家庭成员包括:FamilyID 和当前这个人相等,但是,不包括当前这个人。按人名正序排序。
   [Query(Where="{FamilyID} = @FamilyID AND {ID} <> @ID", OrderBy="{Name}")]
   [Contained]
   Person[] OtherFamilyPersons { get; set; }
}

  回复  引用    
#17楼2006-11-04 22:13 | sss[匿名][未注册用户]
您好,我是个新手
请教个问题,多层结构里面,如果数据库的表结构发生变化,在您的框架里面如何处理?因为需求分析不可能把表结构想得很完美,用户经常要求增减字段,如果分层越多,传递参数也会发生变化,各层代码都要改?
我做过一些小项目,都是不分层的,对多层结构不太了解,感觉多层化后修改起来太麻烦,不知道是不是我理解错了,请问大家是如何处理这类情况的?
比如一个用户注册的表,数据表要加一个住址字段,那么从实体类到应用层一直到表示层的输入表单,都要加传递的参数,岂不是太麻烦了?
谢谢指导

  回复  引用  查看    
#18楼[楼主]2006-11-04 22:19 | Teddy's Knowledge Base      
@sss[匿名]
一般来讲,我们使用Entity作为参数在各层间传递,当数据库结构变化时,也只是Entity的属性有多有少,各层间传递的参数类型没变,这样修改就相对较少了。另外,如NBear,提供实体结构和数据库的同步工具,修改设计实体后,可以使用NBear提供的工具自动重新生成和创建数据库表,从而,自动同步实体和数据库结构。

  回复  引用    
#19楼2006-11-04 22:35 | sss[匿名][未注册用户]
@Teddy's Knowledge Base
非常感谢您的解答,似乎有些明白,正在看您的FLASH教程。

  回复  引用  查看    
#20楼[楼主]2006-11-04 22:45 | Teddy's Knowledge Base      
@sss[匿名]
请注意,flash教程的ORM篇主要是介绍的NBearV2中的ORM实现,由于NBearV3重新实现了整个ORM构架,因此,NBearV2教程中的ORM章节对于使用NBearV3并不具有参考价值。

  回复  引用  查看    
#21楼2006-11-05 10:58 | Jason Cui      
@sss[匿名]
一般来讲,如果不用ORM,你要增加一个字段,需要在所有的用到这个表的SQL语句里修改。如果删除了一个字段,你很可能会忘掉某处,到运行的时候打开那个页面的时候才能发觉。
如果使用ORM,添加字段的时候,只要在映射的类文件里加一个字段,到做绑定的地方加上这个字段就可以了。如果在类文件里删除了一个字段,所有包含这个字段的地方在编译的时候就会告诉你出错了,绝对不会出现忘记改的问题。

  回复  引用    
#22楼2006-11-05 11:12 | zml[未注册用户]
NBear3中有个tutorials例子,其中用db.Sql生成的数据库表和表之间没有主外键约束,这时候运行测试例子没问题,如果在表之间加上主外键约束(如:User和LocalUser)添加LocalUser就会报错。
继承关系的表添加时应先保存基表,在保存子表估计就不会出错了。现有的好像没有考虑保存的顺序。


  回复  引用  查看    
#23楼2006-11-05 11:43 | terry deng      
关于LazyLoad参数有一点疑问,请问假设我有一个有10万条记录的db1数据库关联了db2,那么LazyLoad = false的时候,当我装载db1的10万条记录的时候是不是也会把这10万条记录关联db2的记录也全部装载了,但只执行一次关联查询?而LazyLoad = true的时候,装载db1记录的时候是不是不会把关联的记录也装载,而是在调用相关记录的时候才装载?比如当调用db1[1].db2.字段的时候才装载db1第一条记录所关联db2数据库的记录,并且每调用一次就执行一次关联查询?如果确如上面所说的话,那我这个10万记录的DB1数据库,我运行时只需要用到其中少部分记录的db2关联记录,那究竟LazyLoad是设为false还是True好?如果是true的话,我要调用100条记录的关联记录,那是不是要执行100次关联查询?


  回复  引用  查看    
#24楼[楼主]2006-11-05 14:00 | Teddy's Knowledge Base      
@terry deng
你的理解基本正确。

  回复  引用  查看    
#25楼2006-11-05 14:05 | Jason Cui      
我也想问这个问题。文章表每一行对应用户表的一个记录,通常显示文章的时候肯定会显示用户名,所以这里设LazyLoad=False应该是比较正常的。但是如果我每页显示100条,那后台是不是要执行101条查询?这个太浪费了点吧?我记得ActiveRecord的说明里面,在这种情况下也只需要一条查询语句。(只是文档里是这么写的,是否真的未经查证。)

另外,zml说的这个问题,如果不保存基表,怎么取得主记录的ID?没有这个ID,怎么保存子表?

  回复  引用  查看    
#26楼[楼主]2006-11-05 14:18 | Teddy's Knowledge Base      
@Jason Cui
你说的第一个问题我会再增加缓存支持时一并解决,对于在一组查询中重复载入的有些数据,可以直接从缓存里读,这样就可以最大程度减少性能损失。

这个ID的问题,当实体有继承关系时,不能使用自增长类型的主键,主键总是用户从其它渠道获得的,比如全局ID表,或者干脆使用Guid类型。

  回复  引用    
#27楼2006-11-05 18:47 | lvchaoin[匿名][未注册用户]
有个BUG,在sql语句中的where条件,如 字段1=null 和 字段1 is null是有区别的,如果右边是null值的话,应该用“is”而不是“=”,代码修改如下:
public static WhereClip operator ==(PropertyItem left, PropertyItem right)
{
//if (((object)right) == null)
//{
// return new WhereClip(left.ColumnName + " = " + left.ParamName, right);
//}
//else if (((object)left) == null)
//{
// return new WhereClip(right.ParamName + " = " + right.ColumnName, left);
//}
if (((object)right) == null)
{
return new WhereClip(left.ColumnName + " is null");
}
else if (((object)left) == null)
{
return new WhereClip(right.ParamName + " is null");
}
return new WhereClip(left.ColumnName + " = " + right.ColumnName);
}
请检查是否正确,谢谢:)

  回复  引用  查看    
#28楼[楼主]2006-11-05 19:14 | Teddy's Knowledge Base      
@lvchaoin[匿名]
谢谢报告,我会注意修正!

  回复  引用  查看    
#29楼2006-11-05 20:16 | Jason Cui      
老大有什么办法让我随时知道有最新的版本?总不能每天去刷新十次八次的SF吧,他的网站又慢。
要么开一个专门的文章,用回复来说明发布了新版本,最好能直接把下载地址也放过来,这样要省事很多啊,直接使用“有回复时邮件通知我”就可以了。只是要辛苦一下老大。

  回复  引用  查看    
#30楼[楼主]2006-11-05 20:34 | Teddy's Knowledge Base      
@Jason Cui
可以在sf.net订阅版本更新通知。每次有版本更新就会自动发邮件通知你。

  回复  引用    
#31楼2006-11-07 16:01 | 阿飞[匿名][未注册用户]
假设有两个数据表A和B,而A中有一个字段是B_Id。A表里每一条记录的B_Id都能够在B中找到相应数据;A表中多个记录都可能对应的是同一个B_Id;B表中并不是所有记录都能够在A表中找到相应的数据。而业务逻辑只要求能够从A的记录中找到相应的B就行了。
那么该如何用NBear来描述这两个表的实体关系呢?
我的设计本来是有对应的实体A和B,其中实体A会有一个属性是B。但不知道该怎样用NB来描述这种关系。按这篇文章的说明,可能就是在A里有以下定义:
[Query(Where="{Id} = @B_Id", LazyLoad=true)]
[Contained]
B { get; set; }
但在A里并没有B_Id这个属性定义。能否用这种方式:
[Query(Where="{Id} = @B.Id", LazyLoad=true)]
[Contained]
B { get; set; }
来实现呢?

  回复  引用  查看    
#32楼[楼主]2006-11-07 16:08 | Teddy's Knowledge Base      
@阿飞[匿名]
不行,A实体必须有一个B_ID属性才能像这样定义B:
[Query(Where="{Id} = @B_Id", LazyLoad=true)]
[Contained]
B { get; set; }

如果你不想public暴露B_ID这个属性,你可以把这个属性设为private。

  回复  引用    
#33楼2006-11-07 16:18 | 阿飞[匿名][未注册用户]
哦。。。有没有什么好点的解决方法啊
在A实体有一个B,还有一个B_Id,实在是不好啊。。。

  回复  引用  查看    
#34楼[楼主]2006-11-07 16:28 | Teddy's Knowledge Base      
@阿飞[匿名]
目前只能支持到这样,我会记下,以后考虑支持得更完美。

  回复  引用    
#35楼2006-11-07 16:35 | 阿飞[匿名][未注册用户]
嗯。希望下一版本能够支持啦。。。
  回复  引用  查看    
#36楼2006-11-07 23:46 | Edward.Net      
感觉这样吧查询的语法带入到实体中的Attribute中来好像有点不太优雅,我认为这种关系应该是由ORM自动去构建的。
  回复  引用  查看    
#37楼2006-11-10 20:13 | wqxh      
不错。我现在正在学习用你的框架。希望能越做越好
  回复  引用  查看    
#38楼2006-11-17 23:04 | iceboundrock      
有个想法,如果可以把NBear的教程做成vedio就更好了。atlas和ror都有很多vedio教程,很直观,易于推广
  回复  引用    
#39楼2006-11-22 10:25 | alex[匿名][未注册用户]
对于User的Name这个UserName类型的复合类型,我们也需要设置其SqlType,一般设为ntext,因为,默认情况下复合类型被序列化为XML,并保存于对应的数据库字段。另外,复合类型还必须使用CompoundUnit这个Attribute标记,所以User的Name属性需要被设置成下面这样:
[CompoundUnit]
[SqlType("ntext")]
UserName Name
{
get;
set;
}
有没有可能说 复合类型里面既有数字,又有字符串,这种情况下Name的SqlType怎么设置??

  回复  引用  查看    
#40楼[楼主]2006-11-22 10:28 | Teddy's Knowledge Base      
@alex[匿名]
可以的,只要这个复合类型可以序列化,它可以是任意的class或struct,class的属性同样是可序列化的自定义类型都可以,SqlType是ntext就可以了。

  回复  引用    
#41楼2006-11-24 10:20 | ccp[未注册用户]
我执行到这一步返回为NULL
我得数据库为Access数据库

LocalUser theSavedLocalUser = gateway.Find<LocalUser>(newLocalUser.ID);

请问是什么原因呢

  回复  引用    
#42楼2006-12-05 23:17 | [匿名][未注册用户]
注:大家可能有疑问,为什么这里主键ID能不能是int,并且是自增长的只读属性呢?答案是完全可以的,完全可以设置某个ID属性为下面这样,无需额外设置,它将映射到一个自增长只读的int类型的数据库字段:


看看上面的文字,是不是很不通顺?
比如“为什么这里主键ID能不能是int”。
呵呵,这种语病在文章里多的是,建议能顺一下!

  回复  引用  查看    
#43楼2006-12-05 23:57 | Jason Cui      
呵呵,楼上的可以做做贡献啊。整理一下文档帮老大解决一下问题。
  回复  引用  查看    
#44楼2006-12-11 23:30 | 小楼春雨      
呵呵,偶也坐下沙发
  回复  引用  查看    
#45楼2006-12-15 23:41 | Dah      
4.6 下面的例子
[Relation]
public interface UserGroup : NBear.Common.Design.Entity
{
[RelationKey(typeof(User))]
string UserID
{
get;
set;
}

[RelationKey(typeof(Group))]
Guid GroupID
{
get;
set;
}
}

==> UserID的类型应该为Guid

  回复  引用  查看    
#46楼[楼主]2006-12-16 10:43 | Teddy's Knowledge Base      
@Dah
谢谢提醒,已修复文章中的该笔误。

  回复  引用    
#47楼2006-12-20 22:59 | 洪拾金[未注册用户]
请问NBear支持ORACLE吗?
我看见NBear.Tools.DToEntityDesign.exe可以支持ORACLE的反向工程。
在你后续的教程中又看见配置文件中可以写上各种数据库的连接字符串。
可是为什么NBear.Tools.EntityDesignToEntity.exe工具只能生成的是MSSQL的脚本呢?
如果我把生成的脚本改成ORACLE的并在ORACLE中执行。
然后使用ORACLE的连接字符串。
是否就能很好的支持ORACLE了呢?

  回复  引用  查看    
#48楼[楼主]2006-12-20 23:06 | Teddy's Knowledge Base      
@洪拾金
由于开发精力所限,目前唯一的限制是EntityDesignToEntity还只能支持SqlServer,但是可以先生成表和视图到SqlServer,再Export到Oracle,这样就能同样的使用NBear.Data中的数据访问组件来访问Oracle的数据。

  回复  引用    
#49楼2006-12-21 08:59 | 洪拾金[未注册用户]
谢谢。
还有个疑问。
在实体的级联更新与删除中,会自动的使用SQL语句删除数据库中的相应数据。
但在实际开发中,数据库的程序的服务进程或触发器就可能会直接在数据库内部实现,比如MSSQL就有外键级联更新与删除功能。
那是否就不需要为实体定义关联了呢?
还是有个什么属性来控制是否启用实体的自动级联更新与删除功能?
因为在数据库内部直接实现比用程序调用语句实现要方便节能。

  回复  引用  查看    
#50楼[楼主]2006-12-21 09:06 | Teddy's Knowledge Base      
@洪拾金
是的,FkQuery和ManyToManyQuery这两个Attribute都有一个Contained属性指定是否由NBear处理级联更新删除。如果你不想让nbear处理级联更新,将它设为false就行(默认就是false)。

  回复  引用    
#51楼2006-12-25 17:01 | 洪拾金[未注册用户]
在进行实验中,生成的DB代码已改成ORACLE中并运行成功。
但有几处错误:
一、ORACLE中对INNER连接查询不行,会出现“ORA-03113: 通信通道的文件结束 ”错误!
二、ORACLE中对变量名的长度规定是三十个字符串,而组件中使用“Guid:ToString(N)"是不行的。
三、在“OracleStatementFactory.cs”第五十四行,没有改参数列表长度不等错误,其它文件数据库文件均正确!
四、在此列中,向“User“表插入后,会有一ID号,这是数据库生成的,这时向"LocalUser"插入时,会因为违返外键约束而不能成功,应该在插入第一个表时读取数据库生成的这个“ID”并用此“ID”插入第二个表。
其它一至三个都已改过并运行成功。
第四个很难改呀,涉及的代码太多了。有什么办法吗?

  回复  引用  查看    
#52楼[楼主]2006-12-26 14:53 | Teddy's Knowledge Base      
@洪拾金
对于oracle,目前只能自己注意实体属性的类型的兼容。对于有继承关系的实体,主键值目前只能通过在程序中指定(比如用一个全局的ID表来管理),并赋给实体ID,这样,子类才能正确保存。

  回复  引用    
#53楼2006-12-29 17:21 | foot[匿名][未注册用户]
请问怎样取二个表的值,要用SQL语句吗?????????
  回复  引用  查看    
#54楼[楼主]2006-12-29 17:52 | Teddy's Knowledge Base      
@foot[匿名]
对于复杂查询,一般需要自己建视图或存储过程,nbear可以帮你将返回内容填充到强类型的实体。

  回复  引用    
#55楼2006-12-29 18:04 | foot[匿名][未注册用户]
谢谢!!
  回复  引用    
#56楼2006-12-30 16:03 | aakin[未注册用户]
使用oracle数据库,配置如下:
<add name="ConnectionStringOracle" connectionString="Data Source=kysyqm;User ID=system;password=kys;Unicode=True"
providerName="System.Data.OracleClient" />

调试发现错误如下:

异常详细信息: System.NullReferenceException: 未将对象引用设置到对象的实例。

源错误:


行 49: STATION[] station=gateway.GetPageSelector<STATION>(WhereClip.All,OrderByClip.Default,10).FindPage(1);



  回复  引用  查看    
#57楼[楼主]2006-12-30 16:29 | Teddy's Knowledge Base      
@aakin
你的providerName设置错误,不能是System.Data.OracleClient。

应该设置为NBear.Data.Oracle.OracleDbProvider。

  回复  引用    
#58楼2006-12-30 16:44 | aakin[未注册用户]
谢谢解答,刚才问题解决了,又出现
System.Data.OracleClient.OracleException: ORA-00936: 缺少表达式
怎么回事?

  回复  引用  查看    
#59楼[楼主]2006-12-30 17:55 | Teddy's Knowledge Base      
@aakin
不知道你的oracle版本是什么?
我在oracle10 XE版使用如下代码测试没有问题:
Gateway oracle = new Gateway(DatabaseType.Oracle, "Data Source=localhost;User ID=system;Password=sa;Unicode=True");
TempTable[] objs = oracle.GetPageSelector<TempTable>(WhereClip.All, OrderByClip.Default, 10).FindPage(1);
objs = oracle.GetPageSelector<TempTable>(WhereClip.All, OrderByClip.Default, 10).FindPage(2);

  回复  引用    
#60楼2006-12-31 10:28 | aakin[未注册用户]
谢谢老大指导,我用的是oracle 9i
我对oracle不熟悉,我把语句改成
STATION[] station = gateway.GetPageSelector<STATION>(WhereClip.All, STATION._.CODE.Desc, 10).FindPage(1);就可以了
是不是我的oracle没有设置索引的原因。

  回复  引用  查看    
#61楼[楼主]2006-12-31 11:41 | Teddy's Knowledge Base      
@aakin
有可能,可能是因为数据库表的primarykey或索引没有设置。

  回复  引用    
#62楼2007-01-03 15:10 | aakin[未注册用户]
用oracle9i,如下语句分页显示数据
EVERY_TICKET_RECORD[] station = gateway.GetPageSelector<EVERY_TICKET_RECORD>(WhereClip.All, EVERY_TICKET_RECORD._.CCODE.Desc, listperpage).FindPage(pagenow);
divtbl.InnerHtml = SerializationManager.Serialize(station);
发现记录达到百万级的时候速度很慢,不知道怎么回事。

SELECT "STATUS","BUS_CODE","STATION_CODE","STATION_NAME","SNAME","SCOMPUTER_CODE","SOPERATING_TIME","SREFUND_NOTE_NO","ERROR_NO","VCODE","VNAME","CCODE","CNAME","REGISTER_NO" FROM ( SELECT "STATUS","BUS_CODE","STATION_CODE","STATION_NAME","SNAME","SCOMPUTER_CODE","SOPERATING_TIME","SREFUND_NOTE_NO","ERROR_NO","VCODE","VNAME","CCODE","CNAME","REGISTER_NO", ROW_NUMBER() OVER (ORDER BY "CCODE" DESC) as "DataRow_Pos" FROM "EVERY_TICKET_RECORD" ) "tmp" where "tmp"."DataRow_Pos" > 630 and "tmp"."DataRow_Pos" <= 630 + 15 ORDER BY "CCODE" DESC

  回复  引用  查看    
#63楼[楼主]2007-01-03 15:24 | Teddy's Knowledge Base      
@aakin
nbear默认的分页查询性能确实在百万这样的数据量上是比较慢的。对于大数据量的查询,推荐使用存储过程进行自定义处理。

  回复  引用    
#64楼2007-02-08 14:43 | Tonyyang[未注册用户]
我做WinForm測試是到這裡出錯請問啥原因,public override EntityConfiguration GetEntityConfiguration()
{
if (_PDN_GenProducts_DEntityConfiguration == null)
_PDN_GenProducts_DEntityConfiguration = MetaDataManager.GetEntityConfiguration("Leasear.Entities.PDN_GenProducts_D");
return _PDN_GenProducts_DEntityConfiguration;

}
而用webForm測試沒問題
謝謝!

  回复  引用  查看    
#65楼[楼主]2007-02-08 14:46 | Teddy's Knowledge Base      
你的错误应该是程序找不到EntityConfig.xml文件所致,将EntityConfig.xml复制到winform的exe文件所在的Debug或Release目录应该就好了。
  回复  引用  查看    
#66楼2007-02-10 20:30 | 翁培铖      
俺完全看不懂,真痛苦,现在脱节了
  回复  引用    
#67楼2007-03-04 19:31 | 笑疯[未注册用户]
刚刚的
  回复  引用    
#68楼2007-03-28 10:32 | zicailong[未注册用户]
牛人
有机会会用你框架

taddy让我想起两个人 一个是 那只熊了 另一个是<越狱>里的T-bag

  回复  引用    
#69楼2007-03-28 21:24 | Jinwmmail@126.com[未注册用户]
先说明一下, 我才开始学 NBear, 前面也看过 NHibernate , DAAB ....
觉得这些东东不实用,为什么呢? 做过实际项目就不行,比如用 NHiberanate 开发分布式服务应用,放在中间层,那中间层要实体,做三层就不方便; 做三层只要做好中间层,后面的工作只要前端后更改数据库就好了.

不知 NBear 怎样.

但在这页的实例中,既然引用实体类,为何还 将整个实体的 XML文件用在这,如果一个大项目有很多表,那这个文件有多大? 不实际.

以上为我个人的看法, 我的联系方式: e_mail: Jinwmmail@126.com

请指正.

  回复  引用  查看    
#70楼2007-04-14 02:35 | 狂图      
楼上的, www.alibaba.com.cn 是用hibernate搞的,你认为 实际不实际.hehe
  回复  引用    
#71楼2007-04-15 05:53 | 小菜[未注册用户]
刚开始接触nbear感觉确实很强大,但使用中遇到个问题,请教下
我的2个表如下
表:User
字段:
ID
UserGroup

表:Group
ID
Name

实体设计如下:

interface User:Entity{
int ID{Get;Set;}
[FkQuery("ID", Contained = true, LazyLoad = false)]
Group UserGroup{Get;Set;}
}
interface User:Entity{
int ID{Get;Set;}
string Name{Get;Set;}
}

为什么取user时,user.UserGroup为null

实现User表中UserGroup为外健
上面写法是否正确?正确写发是什么?谢谢指教

  回复  引用    
#72楼2007-04-16 15:23 | gdm[未注册用户]
///////////////////////////////////////////////////////////////////////////
Do you want to know the saved user name's details, which is a compoundunit property? Ok, show you what you want, in fact, it is serialized as xml by the NBear.Common.SerializationManager class, looks like:
<?xml version="1.0" encoding="utf-16"?> <UserName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <FirstName>teddy</FirstName> <LastName>ma</LastName> </UserName>
///////////////////////////////////////////////////////////////////////////

可是在数据库中保存的并不是序列化后的xml呀.
好像是往数据库保存的时候又把它反序列化了吧.
////////////////////////////////////////////////////////////////////////
public global::Entities.UserName Name {
get {
return ((Entities.UserName)(NBear.Common.SerializationManager.Deserialize(typeof(Entities.UserName), this._Name)));
}
set {
this.OnPropertyChanged("Name", this._Name, value);
this._Name = NBear.Common.SerializationManager.Serialize(value);
}
}
/////////////////////////////////////////////////////////////////////////

  回复  引用    
#73楼2007-05-21 13:46 | 何过[未注册用户]
完成这个教程了.就算没啥意见,也要吹毛求疵,从鸡蛋里挑出点骨头出来:
1.虽然说Entities和EntityDesigns没有直接引用,但它们间接“互相”引用。
我在操作过程中EntityDesigns编译通不过,Entities.cs不正确,修改EntityDesigns,须排除Entities.cs,才能正确编译,重新生成Entities.cs并加到Entities,再编译EntityDesigns。这个过程有点烦琐,至于如何更简便,高人们去研究吧。
2.NBear.Tools.EntityDesignToEntity.exe加载了EntityDesigns.dll,VS无法编译EntityDesigns项目,这也比较麻烦。
3.运行gateway.Save<LocalUser>(newLocalUser);这一句,会自动启动MSDTC,不知何解?

还没深入学习。。。。。感谢作者的努力,让我们有这么优秀的框架学习使用研究。

  回复  引用  查看    
#74楼[楼主]2007-05-21 13:52 | Teddy's Knowledge Base      
@何过
1. 可以将SharedTypes那些代码移至一个独立的工程,让EntityDesigns引用,就不会有双向依赖和你说的问题了。

2. 重新编译之前需要先关掉NBear.Tools.EntityDesignToEntity.exe工具,或者可以使用VsPlugin代替手动运行NBear.Tools.EntityDesignToEntity.exe工具,就不会有这个问题了。

3. 所有的写操作默认会使用基于MSDTC的事务,如果不想依赖MSDTC,需要使用asp.net 1.1类型的事务,并且,接着,在所有写操作时,传递tran对象,例如:gateway.Save(newLocalUser, tran)。

  回复  引用    
#75楼2007-06-18 23:16 | jecray[未注册用户]
真是麻烦啊
  回复  引用    
#76楼2007-09-07 11:14 | 游客一号[未注册用户]
好复杂哦,好晕.
  回复  引用    
#77楼2007-09-07 11:15 | 游客一号[未注册用户]
我为什么回晕呢?
  回复  引用    
#78楼2007-09-09 00:31 | 游客一号[未注册用户]
终于明白了。太帅了!正是我朝思暮想的东西。。。。
  回复  引用    
#79楼2007-11-29 23:26 | 不明[未注册用户]
@Teddy's Knowledge Base
刚开始看,还不太明白,对于MYSQL等没有MSDTC的情况下其他数据库这样会有限制吗?
-------------------------------------
3. 所有的写操作默认会使用基于MSDTC的事务,如果不想依赖MSDTC,需要使用asp.net 1.1类型的事务,并且,接着,在所有写操作时,传递tran对象,例如:gateway.Save(newLocalUser, tran)。 回复 引用 查看

  回复  引用    
#80楼2007-12-05 14:01 | zccf[未注册用户]
debug时提示,不知什么原因:
代码> gateway.Save<LocalUser>(newLocalUser); //do you know what is happening when saving the new local user?
Exception:
Invalid object name 'User'.

  回复  引用    
#81楼2008-02-20 11:16 | 枝上柳绵[未注册用户]
您好,谢谢您好的教程,感觉很有收获!
调试时遇到一点问题,请不吝赐教
程序在运行到(调用生成的Entities中的LocalUser)
Entities.LocalUser newLocalUser = new Entities.LocalUser();
时出现“Entities.LocalUser”的类型初始值设定项引发异常。
我的环境并不是WEB程序,只是一个简单的控制台程序,web.config被我改为app.config
因为LocalUser是继承User的,所以我试着实例化User,发现也不成功,同样的错误.
工程编译过程中无任何错误!
查google也没有值得参考的东西,相当郁闷啊!!!
谢谢!!!!!!!

  回复  引用  查看    
#82楼2008-03-11 19:04 | 李海      
谁有flash教程了,我先在下载不了了
  回复  引用  查看    
#83楼2008-03-12 17:08 | 毁于随      
搞了一下午.都照教程上做了.结果在执行语句的时候提示:
将截断字符串或二进制数据。
语句已终止。

似乎是查询语句插入的值大于了字段的宽度.全是我检查了也没有那么长的东西要插入呀.郁闷.

  回复  引用  查看    
#84楼2008-03-12 17:08 | 毁于随      
这个例子要是也能下载就好了!
  回复  引用    
#85楼2008-03-27 15:59 | dugoogle[未注册用户]
当加入引用NBear.Data.dll时,出现System.Security.Policy.PolicyException: 无法获取所需的权限是怎么回事啊,
  回复  引用    
#86楼2008-04-21 11:49 | aneurin[未注册用户]
debug时提示,不知什么原因:
代码> gateway.Save<LocalUser>(newLocalUser); //do you know what is happening when saving the new local user?
Exception:
Invalid object name 'User'.

我试了下,换过版本,以及将外键去掉,都还是同样的结果,即对象名'User'无效
请各位帮助下,谢谢

  回复  引用    
#87楼2008-04-23 09:31 | step_123[未注册用户]
请问一下:[MappingName("")] 与 [Table("")]的区别?
怎么有些版本用Table(v?)有些版本用MappingName(v3.7.2.11)

tks!

  回复  引用    
#88楼2008-06-18 11:32 | alert7[未注册用户]
转载一下,很牛,想学习了!
  回复  引用    
#89楼2008-06-18 11:33 | alert7[未注册用户]
有时间指点本人一下

www.aihua58.cn

本人小站

  回复  引用    
#90楼2008-06-18 11:33 | alert7[未注册用户]

www.aihua58.cn

本人小站

  回复  引用    
#91楼2008-06-18 11:34 | saler[未注册用户]
有时间指点本人一下

www.aihua58.cn

本人小站

  回复  引用    
#92楼2008-06-21 15:39 | saler[未注册用户]
ORM是什么?
对象关系映射(Object Relational Mapping,简称ORM)
详细解译尽在:www.aihua58.cn

  回复  引用  查看    
#93楼2008-07-21 23:11 | 张跃      

我用sql server2005 生成sql脚本执行后,为什么没有办法显示出来关系图呢

不过关系还是存在的

  回复  引用  查看    
#94楼2008-07-30 16:47 | 尚希杰      
有机会用下这个框架
  回复  引用    
#95楼2008-08-31 14:10 | luli327[未注册用户]
为什么一定要搞个框框把自己困起来呢
  回复  引用    
#96楼2008-09-10 20:32 | qweet_xue[未注册用户]
抱歉 在下初学, debug遇到对象名'User'无效 ?? 请问怎么解决?
  回复  引用    
#97楼2009-02-12 21:55 | xiaoguang[未注册用户]
点击Generate DB Script按钮,将生成的代码保存到website工程下的名为db.sql的新文件,但没有保存?