NBearV3.0.0 Preview发布 - 全新ORM实现![11/1 更新:全面支持实体属性级联更新]

11/1 更新:全面支持实体属性级联更新,详见下面的案例的Entity Usage UnitTests代码。

今天发布了NBear的全新版本V3的Preview。

感兴趣的朋友可以从http://sf.net/projects/nbear下载最新源码。

NBearV3相对于V2作了巨大升级和改进。因此不兼容于NBearV2。

之所以目前称为Preview版是因为新版本的源码中除了包含基于NBearV3重写的SimpleGuestbookV1.1之外,还没有任何相关使用文档,并且,实体生成工具仅支持C#,还不支持直接生成VB.NET代码。我会在近期不断补充,并于年内发布V3的正式版。

NBearV3新增/修改功能列表:

1、完全重新设计的ORM实现,支持实体继承,实体间复杂关联(一对一、一对多、多对多)及透明的级联插入、更新、删除,LazyLoad等。
2、提供用于整个开发过程的更易使用的代码生成工具,支持:实体设计代码、实体代码、实体配置文件和数据库创建脚本生成。
3、精简优化了底层数据访问代码,进行了更细致的单线程/多线程性能测试。
4、实体及关联关系可以使用任意标准的.Net Framework支持的语言,使用interface、Attribute、接口继承等语言的自然元素作为实体设计元数据,并使用VS.NET2005的类设计器进行设计。
5、自动生成的实体类是标准的class,避免了V2中基于Emit生成代码的性能损失和可能的内存泄露,集成用于强类型查询的查询代码到每个实体类,并支持标准的各种系统序列化(XML,Binary,WebService SOAP)。生成的实体类代码不依赖于实体设计元数据。
6、对于ServiceFactory部分,增加了SerializationManager类,用于增加自定义类型序列化实现,从而使得service能够支持任意类型的自定义参数和返回值。
7、重新优化设计的Gateway类,新增PageSelector强类型数据分页器,强/弱类型数据访问,批处理数据访问更简洁高效。
8、NBear.Web模块中,删除了UrlRewrite模块。因为,这样的模块市面上太多了,有些也很强大,因此NBear没必要内置一个轻量级实现了。

-

ORM案例演示

这里演示的案例代码包含于源代码中的NBear.Test.CaseTests程序集,演示了一组包含继承关系、复杂关联关系、复合数据类型、枚举类型的实体。

所有的实体关系图如下:



以上的实体关系图是标准的VS2005 IDE的类设计器对于实际的实体设计代码的直观反映。其中User、AgentUser、LocalUser为一组有继承关系的实体。UserProfile为和所有User一对一关联的Profile信息。Group为和所有User多对多关联的Group,UserGroup为关联实体,除了包含用于关联的字段之外,还可以包含多个Weight属性。Domain为和AgentUser和LocalUser关联的Domain,它也是一个多对多关系,关联实体为AgentUserDomain。同时,关联实体支持被关联的实体是多主键的情形。另外,User.Name为一个包含FirstName和LastName字段的struct,这个复合类型映射到一个名为Name的string字段,如何序列化和反序列化这个struct可自定义,而User.Status为一个枚举类型,映射到一个int类型的Status数据字段。

完整的实体设计代码如下:

Entity Design Code

注意,所有的设计实体都使用接口表示,并使用必要的Attribute进行修饰。关于如何使用这些Attribute,近期我会有独立的文档描述,这里大家可以直观感受一下。每个属性的SqlType属性并不是必须的,如果不指定,则代码生成工具将会根据属性的.Net类型使用默认值,特别是对于数值类型,字符串类型建议自定义长度,否则默认为nvarchar(127)。

注意,这里列出的是设计实体代码,所有最终的实际实体(和用于设计的这些代码没有任何依赖来关系)、相关配置信息和数据库生成脚本都能够基于以上设计代码由NBear提供的工具自动生成。生成的具体的代码,我就不演示了。下面简单列举用于操作这些实体的测试代码,包括CRUD和Transaction(11/1更新支持实体属性级联更新,保留更改前的测试代码为黄色,更改后的代码用正常颜色表示)。

以下是支持属性级联更新前的测试代码:

Entity Usage UnitTests

以下是11/1支持级联更新后的代码:

  1using System;
  2using System.Data.Common;
  3using System.Text;
  4using System.Transactions;
  5using System.Collections.Generic;
  6using Microsoft.VisualStudio.TestTools.UnitTesting;
  7
  8using Entities;
  9using NBear.Common;
 10using NBear.Data;
 11
 12using NBear.Test.CaseTests.shared;
 13
 14namespace NBear.Test.CaseTests
 15{
 16    [TestClass]
 17    public class CaseTest
 18    {
 19        Additional test attributes
 47
 48        [TestMethod]
 49        public void TestCreate()
 50        {
 51            LocalUser newLocalUser = new LocalUser();
 52            newLocalUser.ID = Guid.NewGuid();
 53            newLocalUser.LoginName = newLocalUser.ID.ToString();
 54            UserName name = new UserName();
 55            name.FirstName = "first name of local user";
 56            name.LastName = "last name of local user";
 57            newLocalUser.Name = name;
 58            newLocalUser.Password = "password";
 59            newLocalUser.Status = UserStatus.Normal;
 60
 61            gateway.Save<LocalUser>(newLocalUser);
 62        }

 63
 64        [TestMethod]
 65        public void TestFind()
 66        {
 67            AgentUser[] users = gateway.FindArray<AgentUser>(WhereClip.All, OrderByClip.Default);
 68        }

 69
 70        [TestMethod]
 71        public void TestUpdate()
 72        {
 73            LocalUser user = gateway.FindArray<LocalUser>(WhereClip.All, LocalUser._.Password.Desc)[0];
 74            user.Password = "12345";
 75            UserName newName = new UserName();
 76            newName.FirstName = "12345";
 77            user.Name = newName;
 78            gateway.Save<LocalUser>(user);
 79            user = gateway.Find<LocalUser>(user.ID);
 80            Assert.AreEqual(user.Password, "12345");
 81            Assert.AreEqual(user.Name, newName);
 82        }

 83
 84        [TestMethod]
 85        public void TestDelete()
 86        {
 87            LocalUser newLocalUser = new LocalUser();
 88            newLocalUser.ID = Guid.NewGuid();
 89            newLocalUser.LoginName = newLocalUser.ID.ToString();
 90            UserName name = new UserName();
 91            name.FirstName = "first name of local user";
 92            name.LastName = "last name of local user";
 93            newLocalUser.Name = name;
 94            newLocalUser.Password = "password";
 95            newLocalUser.Status = UserStatus.Normal;
 96
 97            gateway.Save<LocalUser>(newLocalUser);
 98
 99            Guid id = newLocalUser.ID;
100            AgentUser user = gateway.Find<AgentUser>(id);
101            gateway.Delete<AgentUser>(user);
102            Assert.IsNull(gateway.Find<User>(id));
103            Assert.IsNull(gateway.Find<AgentUser>(id));
104            Assert.IsNull(gateway.Find<LocalUser>(id));
105        }

106
107        private Guid CreateSampleData(DbTransaction tran)
108        {
109            //create local user
110            LocalUser newLocalUser = new LocalUser();
111            newLocalUser.ID = Guid.NewGuid();
112            newLocalUser.LoginName = newLocalUser.ID.ToString();
113            UserName name = new UserName();
114            name.FirstName = "first name of local user";
115            name.LastName = "last name of local user";
116            newLocalUser.Name = name;
117            newLocalUser.Password = "password";
118            newLocalUser.Status = UserStatus.Normal;
119
120            //create user profile
121            UserProfile newUserProfile = new UserProfile();
122            newUserProfile.ContentXml = "sample content xml";
123            newUserProfile.UserID = newLocalUser.ID;
124
125            newLocalUser.Profile = newUserProfile;
126
127            //create group
128            Group newGroup = new Group();
129            newGroup.ID = Guid.NewGuid();
130            newGroup.IsPublic = true;
131            newGroup.Name = newGroup.ID.ToString();
132
133            newLocalUser.Groups = LocalUser.AddArrayItem<Group>(newLocalUser.Groups, newGroup);
134
135            //create domain
136            Domain newDomain = new Domain();
137            newDomain.Desc = "sample domain desc";
138            newDomain.ID = Guid.NewGuid();
139            newDomain.Name = "sample domain name";
140
141            newLocalUser.Domains = LocalUser.AddArrayItem<Domain>(newLocalUser.Domains, newDomain);
142
143            gateway.Save<LocalUser>(newLocalUser, tran);
144
145            return newLocalUser.ID;
146        }

147
148        [TestMethod]
149        public void TestAsp20Transaction()
150        {
151            Guid id = default(Guid);
152            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
153            {
154                id = CreateSampleData(null);
155
156                scope.Complete();
157            }

158
159            AgentUser user = gateway.Find<AgentUser>(id);
160            Assert.AreNotEqual(user.Domains[0], null);
161            Assert.AreNotEqual(user.Groups[0], null);
162            Assert.AreNotEqual(user.Profile, null);
163
164            user.Status = UserStatus.Deleted;
165            user.Profile.ContentXml = "modified";
166
167            gateway.Save<AgentUser>(user);
168            AgentUser anotherThisUser = gateway.Find<AgentUser>(user.ID);
169            Assert.AreEqual(anotherThisUser.Status, user.Status);
170            Assert.AreEqual(anotherThisUser.Profile.ContentXml, user.Profile.ContentXml);
171
172            gateway.Delete<User>(user);
173            Assert.IsNull(gateway.Find<LocalUser>(id));
174            Assert.IsNull(gateway.Find<UserProfile>(id));
175        }

176
177        [TestMethod]
178        public void TestAsp11Transaction()
179        {
180            Guid id = default(Guid);
181            DbTransaction tran = gateway.BeginTransaction();
182            try
183            {
184                id = CreateSampleData(tran);
185
186                tran.Commit();
187            }

188            catch
189            {
190                tran.Rollback();
191            }

192            finally
193            {
194                gateway.CloseTransaction(tran);
195            }

196
197            AgentUser user = gateway.Find<AgentUser>(id);
198            Assert.AreNotEqual(user.Domains[0], null);
199            Assert.AreNotEqual(user.Groups[0], null);
200            Assert.AreNotEqual(user.Profile, null);
201
202            user.Status = UserStatus.Deleted;
203            user.Profile.ContentXml = "modified";
204
205            gateway.Save<AgentUser>(user);
206            AgentUser anotherThisUser = gateway.Find<AgentUser>(user.ID);
207            Assert.AreEqual(anotherThisUser.Status, user.Status);
208            Assert.AreEqual(anotherThisUser.Profile.ContentXml, user.Profile.ContentXml);
209
210            gateway.Delete<User>(user);
211            Assert.IsNull(gateway.Find<LocalUser>(id));
212            Assert.IsNull(gateway.Find<UserProfile>(id));
213        }

214    }

215}

注意比较CreateSampleData()和TestXXXTransaction()方法的代码。可以看到,支持属性级联更新后,操作实体及关联属性的代码极大简化了!

//本文结束

posted @ 2006-11-01 12:40 Teddy's Knowledge Base Views(6200) Comments(81) Edit 收藏

 回复 引用 查看   
#1楼2006-10-31 19:55 | neuhawk      
支持!!
ado.net 3.0也出ctp了.

 回复 引用 查看   
#2楼2006-10-31 19:58 | dudu      
支持!祝贺!
 回复 引用 查看   
#3楼2006-10-31 20:01 | aspnetx      
支持支持
可惜没占到沙发,呵呵
希望ado.net3出了以后可以很好的融合进去
而不要有什么冲突

 回复 引用 查看   
#4楼2006-10-31 20:05 | 菌哥      
比较激动人心!
严重关注!

 回复 引用   
#5楼2006-10-31 20:34 | 老蒋[匿名]
关注
 回复 引用 查看   
#6楼2006-10-31 21:20 | 高海东      
有个项目做演示最好了
 回复 引用   
#7楼2006-10-31 22:04 | anhwa[未注册用户]
值得关注
 回复 引用 查看   
#8楼2006-10-31 22:12 | try      
严重关注
 回复 引用 查看   
#9楼2006-10-31 22:23 | Vokobo      
期待了这么久,终于有了这么大的动作!
另请问一下,google group 及google svn不会也另开了吧。

 回复 引用 查看   
#10楼[楼主]2006-10-31 23:30 | Teddy's Knowledge Base      
@Vokobo
google group不会变,v2的svn还是会保留。v3会使用新的svn。

 回复 引用   
#11楼2006-10-31 23:38 | lone[未注册用户]
如Teddy所言
v1 》 v2 》 v3
每次都是废了了前面的版本
所以还不敢尝试在项目中使用

 回复 引用 查看   
#12楼2006-11-01 08:00 | 兰亭      
更强了,支持V3。

请问在序列化时,还需要手动将接口转化为对象实体吗?

 回复 引用 查看   
#13楼[楼主]2006-11-01 08:40 | Teddy's Knowledge Base      
@lone
对一个开源项目做向后兼容成本太高了。不过,如果需要,我可以提供V2平滑过渡到V3的solution,可以使需要做修改的工作量最小。

@兰亭
不需要了,因为现在的最终实体本身就是可序列化的class。

 回复 引用 查看   
#14楼2006-11-01 08:51 | 飞鹰      
严重关注
 回复 引用   
#15楼2006-11-01 09:17 | 嘿嘿[未注册用户]
NickLee.Framework
底层采用orm和dataset结合,结合IBatisNet

用orm返回DataSet,动态并完整地sql模式

呵呵,这个也不错,参考blog
www.cnblogs.com/mail-ricklee

 回复 引用 查看   
#16楼2006-11-01 09:18 | 兰亭      
太好了,谢谢,现在用起来更简单了^-^
 回复 引用 查看   
#17楼2006-11-01 09:21 | henry      
实体的设计还是依据表结构,如果能达到这样就好了
[Relation]
109 public interface UserGroup : Entity
110 {
111 [RelationKey("ID")]
112 User UserItem
113 {
114 get;
115 set;
116 }
117
118 [RelationKey("ID")]
119 Group GroupItem
120 {
121 get;
122 set;
123 }
124
125 int Weight
126 {
127 get;
128 set;
129 }
130 }
能否提供关联更新代码用例,对这方面感兴趣。
当序列化User时,相关Groups会被序列化吗?(或根据加方式有关?)

 回复 引用 查看   
#18楼[楼主]2006-11-01 09:33 | Teddy's Knowledge Base      
@henry
我说的是级联更新,主要是指有继承关系的实体的CUD的级联。

提到序列化,应该是在实体设计中有set的话就会在最终实体包含set,这样就能序列化和反序列化,如果实体设计没有set,则最终实体也只有get,自然不会包含于序列化中。

不过经你提醒发现生成工具目前在给设计实体的关联属性加set时漏了生成最终实体的关联属性如Groups等的set代码,已经修正了本地代码,稍后会更新SVN。

大家也可以从SVN of V3下载最新代码:http://nbearv3.googlecode.com/svn/trunk/

 回复 引用   
#19楼2006-11-01 10:02 | Lukiya[未注册用户]
不支持升级………………
 回复 引用 查看   
#20楼[楼主]2006-11-01 10:04 | Teddy's Knowledge Base      
@henry
谢谢建议。你说的方式很不错,不过,我目前的方式有一个好处,就是支持被关联实体是多主键(你这个设计怎样映射多主键?),而且也支持一个关联表关联超过两个实体,比如三元,四元关联。另外,我会考虑在V3中支持关联属性的更新,目前还没有。

 回复 引用 查看   
#21楼[楼主]2006-11-01 10:06 | Teddy's Knowledge Base      
@Lukiya
如果兼容V2就不可能解决V2中很多设计中的问题,我会考虑在V3正式版提供V2实体到V3实体的转换工具,将大家的升级工作量降到最低。

 回复 引用   
#22楼2006-11-01 10:25 | Lukiya[未注册用户]

提几点建议。
1、实体配置文件去掉size的配置是否可行?不然改了size数据库还要改一次xml(nvarchar(64) -> nvarchar)
2、希望加强对存储过程实体工具的支持,如果每个存储过程都手动去写实体真的很麻烦。

以上,想到再来补充。

 回复 引用 查看   
#23楼2006-11-01 10:26 | henry      
@Teddy's Knowledge Base
多主键是可以支持,只是内部的解释上麻烦一点。
(我设计结构时是从来不会考虑多主键的,不过这纯属自己的设计方式)
关联加载方式固定在实体中感觉不灵活,最好是可以让开发人员根据情况选择
不加载(默认),加载所有父,加载所有子和加载指定类型集的关联等。
不过有时候想回来,当User只需CompanyName时确把Comany都加载出来实在有点浪费。

 回复 引用 查看   
#24楼[楼主]2006-11-01 10:31 | Teddy's Knowledge Base      
@henry
关联加载方式固定的问题,你说得没错,我会改为根据配置文件动态决定是否LazyLoad,不固定在实体中。

 回复 引用   
#25楼2006-11-01 10:41 | Lukiya[未注册用户]
尝试3.0时发现点问题

数据库中是nvarchar(128),工具生成的配置文件里是nvarchar(127)?故意的还是怎么回事呢。

 回复 引用 查看   
#26楼[楼主]2006-11-01 11:09 | Teddy's Knowledge Base      
@Lukiya
不会啊,我这里设的127数据库里也是127。你可以将生成的数据库脚本在查询分析器里运行看看生成的数据表的结果,如果真的是127变128,那肯定也只会使数据库的设置问题,因为,归根结底都是运行脚本建的表。

 回复 引用   
#27楼2006-11-01 11:50 | debug[未注册用户]
希望早点出有sdk文档和属于NBear的petshop版本。
 回复 引用 查看   
#28楼2006-11-01 12:30 | finesite      
时刻关注你的NBear 真是NB,领教了 请问你对google的 calendar熟悉吗? 功能很强,有相关的思路和源码文档吗?
 回复 引用 查看   
#29楼2006-11-01 12:47 | stonezhu      
支持强人!!NB!!
 回复 引用 查看   
#30楼[楼主]2006-11-01 12:53 | Teddy's Knowledge Base      
已经更新为V3.0.1,支持实体属性级联更新,另外,关联属性是否LazyLoad也不再固定在实体代码中了,在运行时通过读取Meta信息获得,可以在部署后无需编译修改配置文件进行更改。
 回复 引用   
#31楼2006-11-01 13:02 | Lukiya[未注册用户]
奇怪,我在数据库里改成了nvarchar(120),但是生成的配置文件还是nvarchar(127),是不是默认就是127,需要自己手动改啊?

还有:

<entityConfig>
<includes>
<add key="CmsEntityConfig" value="EntityConfigs/EntityConfigs.xml" />
</includes>
</entityConfig>


提示:
Could not find a part of the path 'C:\Documents and Settings\Administrator\EntityConfigs\EntityConfigs.xml'.

这里配置不支持"~/"吗,难道非要指定绝对路径?

 回复 引用   
#32楼2006-11-01 13:32 | 美娃~西西[未注册用户]
我也支持


不错的在线个人知识管理网站
*** 美娃~西西
大家看看呀

 回复 引用   
#33楼2006-11-01 14:51 | e商[未注册用户]
不错,谢谢哦。
 回复 引用 查看   
#34楼2006-11-01 15:06 | xzwplus      
其实,我一直想看看"双鱼座"有什么评论...
 回复 引用   
#35楼2006-11-01 15:20 | 天天影院[未注册用户]
期待中。
 回复 引用 查看   
#36楼[楼主]2006-11-01 16:23 | Teddy's Knowledge Base      
@Lukiya
更新至v3.0.2版,使得include config支持“~/”,并使得NBear.Tools.DbToEntityDesign.exe能够为SqlServer生成取自元数据库的SqlType了。

 回复 引用 查看   
#37楼2006-11-01 16:50 | 一汐      
“NBear.Data.Gateway”并不包含“Create”的定义??
 回复 引用 查看   
#38楼[楼主]2006-11-01 16:54 | Teddy's Knowledge Base      
@一汐
Create和Update已经全部合并为Save了。

 回复 引用 查看   
#39楼2006-11-01 17:00 | NoMagic      
支持一下!
 回复 引用   
#40楼2006-11-01 17:56 | Kidwind[未注册用户]
@Teddy's Knowledge Base
合并了为什么 SimpleGuestbook 的例子没有更新呢???

 回复 引用 查看   
#41楼[楼主]2006-11-01 18:40 | Teddy's Knowledge Base      
@Kidwind
在v3.0.2中已经更新了。

 回复 引用   
#42楼2006-11-01 20:31 | ct22[未注册用户]
可以用Enterprise Library 的DataAccess Block
替换NBear的Data层数据访问实现么?

 回复 引用 查看   
#43楼[楼主]2006-11-01 20:34 | Teddy's Knowledge Base      
@ct22
NBear的最底层就是基于一个精简优化版本的DAAB实现的,但是,目前已经独立于entilib了,所以不能结合使用。

 回复 引用 查看   
#44楼2006-11-02 07:29 | Stephen Wong      
@Teddy

很高兴看到 NBear 升级了。希望能在实现输出 VB.NET 之前,先提供一些性能测试数据,比较 ADO.NET、DAAB、NBear、NHibernate 在单表CRUD、级联CRUD、并发 SELECT (50个并发~百万级并发(这视你的机器能力而定)) 这几方面的性能数据。

最近在做一个系统,查询并发量初期是10万,年半内目标是300万,就是要在 ADO.NET、DAAB、NBear 之间作一个取舍。NHibernate 和 Castle AR 由于性能问题一早就被舍弃了,就是不知道能不能用 NBear 。在缓存方面 NBear 有什么优势值得我们选择的么?

盼复,谢谢!

 回复 引用 查看   
#45楼2006-11-02 07:32 | Stephen Wong      
另注,我这个系统单表行数是1000万行以上。SQL Server 2005。
 回复 引用 查看   
#46楼2006-11-02 08:02 | 兰亭      
在SPL中有个功能就是在数据表对应的实体类加上一个[IsSaveToMemory=true]标签,就可以将该表中的记录自动加入缓存,同时在添加、修改、删除后自动维护缓存中的数据,这个功能还是很实用的。

另外查询时的TOP N条记录也是很常用的,不知NBear中如何实现?

 回复 引用 查看   
#47楼[楼主]2006-11-02 08:23 | Teddy's Knowledge Base      
@Stephen Wong
如果性能和数据量有如此大的要求,我觉得你不用考虑任何ORM方案,推荐用DAAB+Stored Procedure实现。

@兰亭
关于缓存,从目前的计划来说,因为所有的强类型数据读取都是通过DataReader读的,而DataReader是不能缓存的,所以,最合理的缓存位置还是对强类型实体的直接缓存,我比较倾向于.Net2.0的SqlCacheDependency以及定时过期相结合的方案。SPL的方式我也会参考一下,谢谢你的建议。

对于TOP N是有支持的,如果你使用Gateway.GetPageSelector.FindPage返回第一页,那么就是使用Select Top N实现的。

 回复 引用 查看   
#48楼2006-11-02 08:36 | 风云      
很棒,非常支持,看了你的文章后我写了一篇文章:微软 DLinq技术来临前的国内 .NET 的 ORM 发展之局势

 回复 引用 查看   
#49楼[楼主]2006-11-02 08:48 | Teddy's Knowledge Base      
@风云
看了你的文章,分析得不错。我觉得还应该加上一条重要的:那就是代码生成在ORM中的重要地位,从NHibernate这样一开始不提供代码生成工具而依赖第三方小工具,但现在很多ORM实现,实现功能之前先实现代码生成工具(NBear就是如此),生成实体、元数据配置文件、数据库脚本,能生成的一切。代码生成工具被推到最先,突出了,重视易用性,和对用户的上手速度及维护便利优先考虑的趋势。

 回复 引用   
#50楼2006-11-02 10:08 | 小宝[匿名][未注册用户]
希望能像V2那样兼容SQL语法的查询,毕竟对于大型复杂的查询,要转换成强类型的查询还有点困难,有很多SQL语法的关键字强类型语法都不支持
 回复 引用 查看   
#51楼[楼主]2006-11-02 10:12 | Teddy's Knowledge Base      
@小宝[匿名]
这个目前就是支持的,可以在需要whereclip和orderclip类型的参数的地方直接new whereclip或new orderbyclip,传入sql给构造函数,或设置关联的paramvalues给where。另外,sql中可以使用{ColumnName}, {TableorViewName}, @ParamName这样数据库独立格式的字段和参数名称,框架会将他们解析为相应数据库特有的sql语法。

 回复 引用   
#52楼2006-11-02 11:59 | 小宝[匿名][未注册用户]
搞定了,多谢teddy ,新的v3版本数据访问性能确实有改善了
 回复 引用   
#53楼2006-11-02 13:10 | 冷眼看人生[未注册用户]
请问一个问题:
我在NBEAR3.0的源码里面看到这么一段代码:
public static DateTime GetDateTimeParam(System.Web.HttpRequest request, string paramName, DateTime errorReturn)
{
string retStr = request.Form[paramName];
if (retStr == null)
{
retStr = request.QueryString[paramName];
}
if (retStr == null || retStr.Trim() == string.Empty)
{
return errorReturn;
}
try
{
return Convert.ToDateTime(retStr);
}
catch
{
return errorReturn;
}
}
为什么第一个IF判断条件是retStr == null,我觉得这里应该是retStr == null请指教Teddy's Knowledge Base 指教一下

 回复 引用   
#54楼2006-11-02 13:11 | 冷眼看人生[未注册用户]
写错了,应该是retStr!=null
 回复 引用 查看   
#55楼[楼主]2006-11-02 13:15 | Teddy's Knowledge Base      
@冷眼看人生
代码没错的,你没明白代码的意思。这段代码的意思是,如果Request.Form里没有制定的参数,才检查Request.QueryString。

 回复 引用   
#56楼2006-11-02 13:30 | 冷眼看人生[未注册用户]
谢谢Teddy,是我没想仔细
 回复 引用 查看   
#57楼2006-11-02 20:36 | 双鱼座      
深度关注中...
 回复 引用   
#58楼2006-11-02 20:56 | nbear_newbie[未注册用户]
请问连接SQL SERVER 2005 EXPRESS的数据库,才connection那边该怎么写,我试了多次总是出错,能给个例子吗
 回复 引用 查看   
#59楼[楼主]2006-11-02 20:58 | Teddy's Knowledge Base      
@nbear_newbie
你可以参考cases目录下的SimpleGuestbook中的Web.config中的connectionstring设置,其中包含两个connectionstring,一个是for Access的,另一个就是for SQL Server 2005 Express的。

 回复 引用   
#60楼2006-11-02 21:15 | nbear_newbie[未注册用户]
我就是从那考的连接字符串
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SimpleGuestbook.mdf;Integrated Security=True;providerName=NBear.Data.SqlServer9.SqlDbProvider9
老是报错 说是不支持关键字providerName

 回复 引用 查看   
#61楼[楼主]2006-11-02 21:19 | Teddy's Knowledge Base      
@nbear_newbie
晕倒,你别把providerName也包括进去呀,注意connectionstring只是前面这段:

Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SimpleGuestbook.mdf;Integrated Security=True

不包括providerName的。

 回复 引用   
#62楼2006-11-02 21:19 | nbear_newbie[未注册用户]
我指的是在DBToEntityDesigner那边的Connection
 回复 引用 查看   
#63楼[楼主]2006-11-02 21:22 | Teddy's Knowledge Base      
除了在Web.config种之外,其他地方你要将connectionstring中的|DataDirectory|\SimpleGuestbook.mdf替换为绝对路径的,并且,有时要将Integrated Security=True这句去掉。也就是说,实际的connectionstring可能是下面这样的:
Data Source=.\SQLEXPRESS;AttachDbFilename=绝对路径\SimpleGuestbook.mdf

 回复 引用   
#64楼2006-11-02 21:23 | nbear_newbie[未注册用户]
这是我一开始的连接字符串
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|D:\Visual Studio 2005\NBearV3\cases\SimpleGuestbook\website\App_Data\SimpleGuestbook.mdf;Integrated Security=True
我的程序放在D:\Visual Studio 2005\NBearV3
说是不支持路径格式,所以我就把providername也加上去试了,又把路径改成\SimpleGuestbook.mdf;
这样都出错,实在没法了

 回复 引用 查看   
#65楼[楼主]2006-11-02 21:26 | Teddy's Knowledge Base      
@nbear_newbie
设成:

Data Source=.\SQLEXPRESS;AttachDbFilename=D:\Visual Studio 2005\NBearV3\cases\SimpleGuestbook\website\App_Data\SimpleGuestbook.mdf

就可以了。不要包含“|DataDirectory|”。

 回复 引用   
#66楼2006-11-02 21:31 | nbear_newbie[未注册用户]
谢谢,这样改了就连上了,能为我解释下|DataDirectory|吗,今晚实在麻烦你了
 回复 引用 查看   
#67楼[楼主]2006-11-02 21:36 | Teddy's Knowledge Base      
@nbear_newbie
对于Web.config中的connectionstring中的|DataDirectory|,他就代表了~\App_Data这个路径。也就是说|DataDirectory|\SimpleGuestbook.mdf等价于~\App_Data\SimpleGuestbook.mdf。

 回复 引用   
#68楼2006-11-02 22:46 | 来不及登录[未注册用户]
@Teddy's Knowledge Base
在SVN里拿到了SDK的帮助文档,但都是E文。这下可苦了我们这些E文不好的人了。以前V2还有中文的呢!能不能辛苦你把中文文档也弄出来啊。谢谢!

 回复 引用 查看   
#69楼2006-11-03 10:00 | 无赖.net      
问个问题:这个类 public class CryptographyManager
是不是没有用起来,查找引用不到,
我是想学习下如何加密连接字符串,和用户密码。谢谢!

 回复 引用 查看   
#70楼[楼主]2006-11-03 10:08 | Teddy's Knowledge Base      
@无赖.net
cases\SimpleGuestbook的代码中包含了使用CryptographyManager 的hash加密用户名密码。其他的对称加密/解密方法使用时需要传入一个标准的.Net Framework的对称加密解密算法实现类实例,你可以在MSDN中查找哪些类实现了SymmetricAlgorithm这个基类,传递一个该基类的实现类的实例给方法的参数就可以了。

 回复 引用 查看   
#71楼2006-11-03 10:10 | 无赖.net      
@Teddy's Knowledge Base
非常感谢!!:)

 回复 引用 查看   
#72楼2006-11-03 15:39 | Jason Cui      
内置分页是否支持Sql Server 2005的Row_Number()?
 回复 引用 查看   
#73楼[楼主]2006-11-03 17:06 | Teddy's Knowledge Base      
@Jason Cui
是的,使用SqlServer9这个provider时就会使用Row_Number()来改善分页查询的性能。

 回复 引用   
#74楼2006-11-05 16:07 | lvchaoin[匿名][未注册用户]
在web.config文件中配置如下节后:
<entityConfig>
<includes>
<add key="Sample Entity Config" value="~/EntityConfig.xml" />
</includes>
</entityConfig>
编译时候始终报错:
无法识别的配置节 entityConfig。
该怎么处理,学习Nbear的朋友们知道的回复一下啊,谢谢:)

 回复 引用 查看   
#75楼[楼主]2006-11-05 16:10 | Teddy's Knowledge Base      
@lvchaoin[匿名]
你可能忘了设置Web.config中的
<configSections>
<section name="entityConfig" type="NBear.Common.EntityConfigurationSection, NBear.Common" />
</configSections>
,另外别忘了让website引用NBear.Common.dll

 回复 引用   
#76楼2006-11-05 16:13 | lvchaoin[匿名][未注册用户]
另外还有个问题,如下语句:
return Gateways.Permission.FindArray<Entities.MODULE_TYPE>(MODULE_TYPE._.PARENT_ID == null, MODULE_TYPE._.ID.Desc);
报错为:未将对象引用设置到对象的实例。
搞的我很晕了,望指导,谢谢:)

 回复 引用 查看   
#77楼[楼主]2006-11-05 16:27 | Teddy's Knowledge Base      
@lvchaoin[匿名]
这个bug已经在v3.0.8中修复。现在已经可以从sf.net下载:http://sf.net/projects/nbear

 回复 引用   
#78楼2006-11-05 16:32 | lvchaoin[匿名][未注册用户]
哦,谢谢,我用的是3.0.7的版本,今天早上下载的,没有即时关注!:)谢谢
 回复 引用 查看   
#79楼2006-11-10 22:12 | MK2      
@Teddy's Knowledge Base
看了SDK,
public EntityType[] FindPage(
int pageNo
)

就是说想返回第二页,就FindPage(2)就行咯?返回类型是EntityType[]?

 回复 引用 查看   
#80楼[楼主]2006-11-10 22:18 | Teddy's Knowledge Base      
@MK2
是的。

出售蓝奇高级验证码识别引擎,可准确识别新浪动网淘宝CSDN等多种复杂验证码。

输出为一个标准DLL,可供VB,VC,Delphi,C#.NET,VB.NET,模拟精灵,按键精灵等多平台调用,调用方法简单,几行代码即可完成。独具特色的边缘检测字符分离、旋转倾斜纠正和通用字符匹配算法(无论字体和大小), 使得该引擎对于像新浪、动网、淘宝、CSDN等多种验证码均有不错的识别率,是一款效果较为理想的验证码识别引擎。附详细的调用实例和代码注释等相关技术文档。

官方网站 - http://***/yzm_advocr
识别效果怎么样一试就知道 - DEMO下载 http://***/yzm_advocr/advocr.rar