`

NBear常见问题集 -- 摘自NBear Google Group

 
阅读更多

【IT168知识库】
 

摘自 NBear Google Group 

1. LazyLoad顾名思义,就是,这个属性只在第一次真正访问时,才会从数据库读取数据,不访问就不会取数据,这样就能避免不必要的数据库读取。

2. 发布NBearV3.1.7,包含重要升级内容:强类型实体集合­、Gateway缓存等

   1、强类型实体集合 

新增的强类型实体集合会将设计实体中的Domain[] Domains这样的数组形式的关联属性,生成为最终实体中的DomainArrayList 
Domains属性。 

每一个实体,如Domain都会多生成一个形如DomainArrayList的集合类型,使用该集合可以添加、删除、清空关联到属性的对象。当属性设置Con­tained时,和原来使用Domain[] 
Domains一样,能够自动级联更新/删除。原来的Entity.AddArrayItem/RemoveArrayItem等方法已经删除。 

    2、为Gateway新增简单的缓存支持。可以以如下格式配置config文件,注意cacheConfig配置节。 
<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
  <configSections> 
    <section name="entityConfig" type=" 
NBear.Common.EntityConfigurationSection, NBear.Common" /> 
*    <section name="cacheConfig" type="NBear.Data.CacheConfigurationSection, 
NBear.Data" />* 
  </configSections> 
  <entityConfig> 
    <includes> 
      <add key="Sample" 
value="C:\Teddy\NBearV3\src\NBear.Test.UnitTests\EntityConfig.xml" /> 
    </includes> 
  </entityConfig> 
*  <cacheConfig enable="true"> 
    <cachingTables> 
      <add key="Northwind.Orders" value="5" /> 
    </cachingTables> 
  </cacheConfig> 
*  <connectionStrings> 
    <add name="Northwind" 
connectionString="Server=(local);Database=Northwind;Uid=sa;Pwd=sa" 
providerName="NBear.Data.SqlServer.SqlDbProvider"/> 
  </connectionStrings> 
</configuration> 

这里的每一项add可以指定一个数据库表或存储过程的名称和缓存的时间(单位:秒)。 

例如,Northwind.Orders中,Northwind 
表示对应的ConnectionString配置节的名称,Orders是数据库中的表名(注意是表名而不是实体类的名称)或存储过程名称。 

当如上配置后,默认的以Northwind这个ConnectionString初始化的Gateway实例将是自动开启了读缓存支持的。 
可以使用Gateway.TurnOnCache()/TurnOffCache()方法改变当前Gateway实例是否使用缓存。 

一般来讲,对于每一个ConnectionString,我们可以实例化两个Gateway,一个专门用于有缓存的读数据,另一个用于无缓存的读数据。另一方面­,无论是否开启缓存支持,对于写操作没有影响。 

   3、Entity.EntityArrayToDataTable()现在支持输入一个空数组或者null返回一个只包含实体结构的空的DataTable实例­。 



所有工具生成的最终实体代码都是partial类,你可以在独立的文件建partil类来扩展这些实体,比如添加方法,自定义属性什么的。part­ial类带来的额外好处是,当实体设计有变化时,只要类名没变化,重新生成最终实体代码不会破坏独立的partial类的代码,维护和升级就很轻松了。 

User的ID不是只读的,就算设计实体中是只读的,最终的实体中也是可写的。


3. 从NBearV3.2.2 Beta 版开始:

    1、更全面的自增长主键支持。现在即使是有继承关系的实体,也可以设置自增长主键了。 

    2、自动Guid主键支持。原来,如果使用Guid作主键,必须手动设置新建实体的主键值。在新版本中,如果使用Guid主键,如果没有为主键设置值,NBea­r会在Save时自动为它生成一个值。因此,您将能和int自增长字段类似使用Guid主键的实体。 

    3、自动设置关联属性。原来的版本中,如果Profile是User的属性,但是,Profile包含一个UserID外键属性,则保存user前需要手动设置­Profile的UserID为当前user的ID;在新版本中,这样的关联属性无需再手动设置,凡是设置到User的对象,save 
user时,这些关联属性会自动从user中获取。 

4. 在NBearV3中有什么方法设置某一实体字段的默认值
可以为entity写一个partial的构造函数进行额外的实体属性初始化,比如设置特殊的实体的初始值。 

5. NBear做数据库设计必须要先设计那一堆的实体代码和接口,然后再生成数据库表吗? 
数据库本身的建模能力是非常有限的,并不能描述复杂的ER关系的,所以注定了,如果先数据库再实体,那么,是很难映射复杂OO模型的。 
同时,NBear提供了DbToEntityDesign.exe工具, 
可以先为将数据库表生成设计实体,再从设计实体到新的数据库和实体代码。从而方便整合现有系统,当然一定程度上也支持数据库到实体的设计方法。 

6.实际开发中经常碰到这样的问题,请问NBear是否提供了解决方案: 

(1)要取出某表中符合特定条件的记录,例如某int型的字段大于10的记录。或者某字段in 
(1,2,3)的记录(或not 
in,between等)。还有取出前n条,如top 10之类。 

(2)对多表查询,NBear是如何处理的?如下表 
字段A  字段B  字段C 
1          2           aaa 

其中A和B来自一个表,C来自另个表。首先如何将这个列表呈现出来?如何将2个实体的结果拼起来?是否一定要用视图? 

(3)对于日期查询,要查找某DateTime类型的字段介于2个时间之间的,怎么处理? 

(4)是否支持存储过程级的分页?这个对性能影响很大。 

(5)是否支持事务?比如更新一个主表,再更新其子表,那么这2个操作应在一个事务里完成,默认的Containd=true的更新是放在事务里的吗?如果不是,­能么能否提供一个调用事务的例子? 

(6)关于批量更新,如我要把主表里主键为1的那条记录,它在子表中的所有行的某个字段全部更新一下,如何处理? 

1、支持,对用常用的查询,NBear提供了强类型查询语法,对于复杂查询,NBear也提供直接使用sql的查询条件,并且在同一个查询中,强类型条件和sq­l条件可以组合混用,你提到的这些都有办法非常方便的支持。 

2、对于这类复杂查询,以及分组查询等,需要建视图来支持。 

3、对于日期范围,可以以自然的方式处理,比如查询条件可以类似:Article._.PostTime > DateTime.Parse("2006-1-1") 
& Article._.PostTime < DateTime.Parse("2006-1-5")。 

4、默认的分页并不使用存储过程实现,但是,NBear支持读取存储过程,返回强类型实体,所以对于高性能查询要求,可以使用自定义的存储过程来实现。 

5、是的,所有的级联更新全都包含于事务,并且,在数据库中,所有有关联关系的表都是自动生成了依赖约束的,即使通过外部的程序读写数据库,也不会破坏数据完整­性。 

6、完全支持,Gateway.BatchUpdate和BatchDelete方法提供了强类型的批量更新和删除支持。以批量更新为例,查询类似: 
gateway.BatchUpdate<User>(new PropertyItem[] { User._.Status }, new object[] 
{ UserStatus.Deleted }, User._.GroupID == 1); 

Teddy 

BatchUpdate的更新语法:第一个参数指定哪些列要更新,第二个参数指定第一个参数指定的要更新的列的更新数据,第三个参数表示被更新的记录的条件。 


7. 原来,我会为标注FkReverseQuery的属性自动生成外键约束,但事实证明是不行的,像这种情况就不能设置外键约束,否则,root元素的Parent­ID就不知放什么值了。所以我已经改成,不自动对FkReverseQuery属性生成外键约束了,如果需要外键约束的,需要同时标注FriendKeyAtt­ribute。 

8. 当获取一个实体后,进行了某几个字段的修改,怎么样才可以只提交更改字段的更新. 
如果是全部更新不必要,如:日志表中有类别,内容,如果只修改类别,就不需要提交内容 
的修改
. 

正常情况下,保存一个实体时,只有修改过的字段会被包含进sql语句执行更新的。你可以通过Gateway.SetSqlLogger()设置sql 
logger来跟踪实际的sql。 
Teddy 

9. top相关的语法
V3当然是支持的,请参考,ORM_Adv教程。另外,Gateway.GetPageSelector 
().GetPage(1)返回第一页时,就是通过top语法来读取数据的。 
Teddy 

10.  [FriendKey(typeof(Category))] 
        [MappingName("CategoryId")] 
        int CategoryId 
        { 
            get; 
            set; 
        } 

        [NotNull] 
        [CustomQuery("{CategoryId}=@CategoryId",LazyLoad = true)] 
        Category Category 
        { 
            get; 
            set; 
        } 

11. 服务器 'SERVER' 上的 MSDTC 不可用
如果使用默认的事务处理,需要开启服务器的msdtc服务,因为,默认的事务使用System.Transactions来处理, 
他会检测msdtc是否开启。如果服务器不想运行msdtc的话,也希望程序能正常运行的话,则需要显式的使用Gateway.BegnTransaction 
()方法开始一个事务,并对所有的写操作,显式传递该tran参数,就是类似.net1.1的传统的事务处理。 

Teddy 

这个问题2.*我就提过了,不要在互联网模式下使用msdtc。目前还没有好的解决方案。 
如果要用,请把两台机器做成虚拟网后使用。 

或者你直接用DbTransaction,而不要使用TransactionScope 
原因可参考:当事务遇到防火墙 

(打开MSDTC的方法与问题集: http://zhidao.baidu.com/question/1614423.html)

12. 试试最新的v3.4.0版中的In方法

       T_Sell[] GetSaleDataByCity(string fac_Code, string[] City_ID) 
       { 
           return Gateway.Default.FindArray<T_Sell>(fac_Code == 
T_Sell._.Fac_Code & T_Sell._.City_ID.In(City_ID), OrderByClip.Default); 
       } 

13. 如何设计实体关系来更好的实现跨级查询

比如有Category、Product、Item三个实体,Category与Product之间,以及Product与Item之间都是1对多的关系。 

如果我想直接查询某一个Category下面的所有Item,除了先返回Product[],再返回Item[],是否还有好的办法,可以减少实际产生的SQL­语句。 

没有特别方便的办法,不过,一般,复杂(关联)查选,建议用存储过程查询或直接用sql查询,将返回的结果填充到实体。 

例如,可以使用Gateway.FindArray<Entity>(string sql, params object[] 
paramValues)重载使用自定义sql查询返回Items,但是注意,自定义sql的select的列的顺序必须和Item的属性定义一致。 

Teddy 

14. 查询和事件相关的条件也可以直接用Gateway处理的,例如,当天,比如今天是2006-12-5,其实也就是说,所有的新闻中AddTime大于等于200­6-12-5 
0分0秒并且小于2006-12-6 0分0秒的News。那么可以这样查询:Gateway.FindArray<News>(News._.AddTime >= 
DateTime.Parse("2006-12-5") & News._.AddTime < DateTime.Parse("2006-12-6") ); 

15. 用Gateway那个方法可以实现?求表一字段的最小值.

可以先用object minPrice = Gateway.Min<Product>(WhereClip.All, 
Product._.price)获得最小的价格,再用Gateway.Find<Product>(Product._.price == 
minPrice);得到这个Product。 

16.  public static bool Save(Category category)
       {
           Category cat = new Category();
           cat.ID = category.ID;
           cat.Attach();
           cat.Name = category.Name;
           cat.Description = category.Description;

           return _categoryService.Save(cat);
       }

17. 返回一个IDataRe­ader方法 :需要查询sql返回IDataReader可以使用Gateway.DbHelper中的方法。 

18. 如何设置自增的主键?

如下定义就可以了,定义只读的int或long的主键,将自动映射为自增长字段: 
[PrimaryKey] 
int ID { get; } 
Teddy 

19. [PrimaryKey]  应该建立的是聚集索引吧,但有时不想在主键上建立聚集索引,想在其它字端上建立咋办? 
在运行完NBear生成的sql脚本之后,可以定义一个自定义的sql脚本执行自定义的数据库修改以及初始数据的填充等。 
NBear只是默认提供比较常用的情况的脚本,复杂情形还是要用户自己来控制的和初始化的。 

20. 一个表,比如 
ID,ParentID 
我现在让顶级ID的ParentID为空,请问Save如何做? 
问题1:在定义的时候如果定义成 int? 
ID,这样生成的实体类是错误的 
问题2:既然不能定义int?,那么ID怎么能够为空呢? 

*我说的就是自连接!!* 

下面这样定义: 

public interface Node : Entity  //部门 

    [PrimaryKey] //自身主键 
    int ID { get;  set;} 

   [FkReverseQuery] 
   Node ParentID { get; set; } 

 



Parent对应的ParentID默认就是int?的。你不给它赋值他就是null。

21. gateway.FindArray<...>()默认的是"SELECT * FROM 
Table",请问如何可以只选择某几个字段,而不是选取全部字段,不要说用gateway.Db里的方法。 
还有,SQL语句中的一些关键字如何实现,比如TOP、in、between、Distinct等等,Entityspace里这些方面就实现得很好 

1、只选择某几个字段目前必须定义包含需要的列的专门的只读(标注ReadOnly)设计实体。 

2、只需要使用Gateway.GetPageSelector().GetPage(1)方法独取第一页就是使用TOP语法查询的。 

3、聚合查询Gateway.Count是支持Distinct的。 

4、最新的v3.3.9版已经增加In和Between查询支持了。可以类似User._.Price.Between(1000, 
5000)和User._.ID.In(1, 3, 5, 6, 10)这样的语法进行查询。 


22.  使用Gateway.Default.GetPageSelector<>时,如果我有100条数据.我想得到排序后,从第20条-第70条的数据怎么­得到

没有直接的方法,不过你可以组合几个方法来实现: 

比如,如果排序字段值唯一,你可以找到第19个的排序字段,在查询第20个开始的前50条记录。 

或者,你也可以先查询得到前19条记录的Id,存到一个数组ids,再查询gateway.GetPageSelector<Entity>((!Entity­._.ID.In(ids)), 
OrderByClip.Default, 50).GetPage(1) 

数据绑定到GridView后对数据进行删除时,会不会自动更新? 
不行。以Entity的形式邦定到GridView时,Entity都是无状态的,不能像邦定DataSet那样维持可更新的状态。

23. Gateway.Default默认数库是哪儿个?
Gateway.Default默认对应ConnectionStrings配置节中的最后一个数据库连接。 

24. 我用的是托管空间,使用NBear会不会遇到不能解决的问题

不会,但是,用于托管空间的话,要注意一点:对于每一个写操作,必须显式使用Gateway.BeginTransaction 
()方式的事务,并在传递tran参数,否则会报msdtc服务未开启错误。 

例如,Save操作必须象下面这样执行: 

DbTransaction tran = Gateway.BeginTransaction(); 
try 

  gateway.Save(entityObj, tran); 

  tran.Commit(); 



catch 

  tran.Rollback(); 
  throw; 



finally 

  gateway.CloseTransaction(tran); 

 



25.
Like类似下面这样使用:

gateway.FindArray<User>(User._.Name.Like("%hewei%"));
 
就相当于Sql语句中的like操作符。right自然表示like操作符右边的值。
Like是忽略大小写比较的,%表示通配符,%hewei%表示不需分大小写的任意包含hewei的Name,而只用hewei只代表不需分大小写的Name等于hewei。

26. 以NBearV3\tutorials\IoC_Tutorial做为例子
____________________________________________
Default2.cs:
IProductService ps = factory.GetService<IProductService>();
Product[] products = ps.GetAllProducts();
this.GridView1.DataSource = products;
this.GridView1.DataBind();
____________________________________________

Default2.aspx:
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False">
           <Columns>
               <asp:BoundField DataField="productname" />
               <asp:BoundField DataField="categoryname" />
            </Columns>
       </asp:GridView>

提示没有categoryname字段,  LazyLoad =
false应该products实例化后products.Category.CategoryId和products.Category.CategoryName也取出来了
有什么方法在前台显示products.Category.CategoryName吗?

如果这样的绑定很常用,可以在Entities工程的一个独立的cs文件中,写一个partial Product类来为Product扩展一个CategoryName属性:
 
public partial Product : NBear.Common.Entity
{
  public string CategoryName
  {
    get
    {
      return this.Category.CategoryName;
    }
  }
}
 
这样你的代码就能正常运行了。
 
Answer:
可以将City_ID改为一个City实体。然后为Consumer写一个partial 
class,添加一个CityName属性,简单返回Consumer的City实体的Name属性。
还有一个办法是在保留City_ID的情况下,为 Comsumer增加一个 CustomQuery的City属性,这样能既保留City_ID操作的方便性,又能获得查询City的便利:
 
//CustomQuery的第一个参数的意思是:City实体的City_ID属性(由{City_ID}表示)的值等于当前Comsumer实例的City_ID属性(由@City_ID表示)的值。
[CustomQuery("{City_ID} = @City_ID")]
City { get; set; }

28. "事务已被隐式或显式提交,或已终止。" 

数据库在本机的时候,没有出现该问题。 
但数据库与程序不在一台机器时,做数据库写操作就会出现这个问题。 

你使用的是默认的基于msdtc的事务还是基于Gateway.BeginTransaction 
()的事务呢?如果是前者,建议改为后一方案试试,因为最有可能的原因还是默认的基于msdtc的事务的问题。在本机调试时,由于数据库在同一机器,msdtc­总能工作正常,跨机器时可能就会受各种原因的影响,比如防火墙等。 

Teddy 

29. "NBearLite批处理是否可以在不同表中同时执行":

比如,我先向A表中批量插入10条数据,然后再向B表中添加10条记录, 
请问这两步操作能否合并成一步?即一次性向A表和B表插10条记录, 
而不是分开执行? 
Teddy: 可以

30. NBear中实体设计时,复合主键怎么设置啊?

将两个以上的字段标注PrimaryKey就可以了。 
Teddy 

31. 对于Oracle的自增量字段,NBear如何处理?
Oracle中的自增量是通过Sequence来实现的,就是插入时用 
insert into table (id) values(sequece.nextval) 
那么在用Nbear写该实体的insert代码该如何写呢? 
Table tb=new Table(); 
       tb.id=?? 
       GateWay.Save<Table>(tb); 

Answer:
NBearV3 对Oracle SEQ的设置方法,可以参照这里: 
2007/1/13 
Version 3.5.5 

Updates: 

1) Enhance NBear.Data to support sequence based autoincrement primary key. 
   To enable autoincrement primary key for oracle, you must create sequence 
and trigger for each table like below: 

   CREATE SEQUENCE SEQ_TABLENAME; 

   CREATE OR REPLACE TRIGGER TABLENAME_AUTOINCREMENT 
   BEFORE INSERT ON "TABLENAME" 
   FOR EACH ROW 
   WHEN (NEW.ID IS NULL) 
   BEGIN 
   SELECT SEQ_TABLENAME.CURRVAL INTO :NEW.ID FROM DUAL; 
   END; 
只要按这个规则建好SEQ,Insert时没有什么特别,save就可以了。 

Teddy 

分享到:
评论

相关推荐

    Nbear ORM

    **Nbear ORM 开源框架详解** NBear ORM(Object-Relational Mapping)是一个高效、灵活且功能强大的.NET数据访问框架,旨在简化.NET开发者与数据库之间的交互。它通过提供对象关系映射功能,使得开发人员可以使用...

    NBear

    NBear是.NET平台上的一个高性能、轻量级的ORM(对象关系映射)框架,它在.NET编程领域中被广泛使用。NBear2.5.0版本是该框架的一个重要迭代,提供了许多新特性和改进,旨在提升开发效率并优化数据库操作性能。 首先...

    ASP.NET框架:NBear

    7. **多数据库支持**:NBear不仅支持常见的关系型数据库,还支持NoSQL数据库,如MongoDB,增强了其在不同场景下的适用性。 在使用NBear时,开发者首先需要配置数据库连接信息,然后通过NBear提供的工具生成实体类和...

    NBear访问多个数据库

    标题中的“NBear访问多个数据库”指的是使用NBear框架在应用程序中实现对多个数据库的并发访问。NBear是一个开源的.NET ORM(对象关系映射)框架,它提供了一种高效、灵活的方式来操作数据库,而无需编写大量的SQL...

    Nbear

    ** 请修改扩展名为ZIP Nbear V3.7.2源代码 类库 VS插件等

    使用NBear项目模板快速建立项目框架

    NBear是一个高性能、轻量级的.NET ORM(对象关系映射)框架,它提供了一种简单而强大的方式来处理数据库操作。在这个主题中,“使用NBear项目模板快速建立项目框架”意味着我们可以借助NBear提供的项目模板,高效地...

    ASP.NET-[论坛社区]NBear+NBear开发BBS系统源码.zip

    [论坛社区]NBBear+NBBear开发BBS系统源码_nbearbbs.rar",可以帮助开发者深入了解ASP.NET和NBear的结合使用,理解如何在实际项目中应用ORM框架,提高开发效率,同时也可以学习到论坛系统的常见设计模式和架构。...

    NBear3.6.6

    - **使用提示**:可能会包含一些使用技巧、注意事项或常见问题解答。 7. **dist** 文件夹: - **发布文件**:dist 文件夹通常包含NBear3.6.6的编译后的库文件和其他部署所需资源,方便用户在项目中直接引用。 综...

    NBear源码与帮助文档

    NBear是一款针对.NET Framework开发的高性能、轻量级的ORM(对象关系映射)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式处理数据。NBear在.NET社区中享有较高的声誉,因其高效、灵活和强大的特性而...

    nbear_petshop.1.0.0

    《NBear框架详解——以nbear_petshop.1.0.0为例》 NBear框架,作为一款基于C#语言的高性能、轻量级的ORM(对象关系映射)工具,为开发者提供了强大的数据访问能力,极大地提高了开发效率。本文将深入探讨NBear框架...

    Nbear使用手册

    Nbear使用手册(版本: 2.4.1)

    NBear+Anthem 应用案列

    NBear是一款高性能、轻量级的.NET ORM(对象关系映射)框架,而Anthem则是一款强大的UI控件集,主要用于ASP.NET平台,提供了丰富的用户界面元素和交互体验。 首先,NBear作为一个ORM框架,它简化了.NET开发者与...

    NBearV3.rar_nbear

    总的来说,NBear是一个全面而实用的开发框架,旨在解决.NET平台上的各种常见问题,帮助开发者快速构建稳定、高效的应用程序。通过使用NBear,开发者可以将更多的精力放在业务逻辑上,而不是基础架构的搭建,从而提高...

    Nbear中文帮助手册

    《NBear中文帮助手册》是针对NBear框架的详尽指南,它涵盖了NBear的核心功能和使用方法。NBear是一个全面的.NET开发框架,旨在提供高效、便捷的数据持久化、序列化以及服务处理能力,特别适合ASP.NET开发环境。下面...

    NBear+NBear开发BBS系统源码_nbearbbs.zip

    NBear是一个高性能、轻量级且易于使用的.NET框架,它主要设计用于简化...通过研究NBear BBS系统源码,开发者不仅能掌握NBear框架的使用,还能深入了解BBS系统的架构设计和常见功能实现,对提升.NET开发能力有很大帮助。

    NBearV3.7.2_doc

    - **问题排查**:常见问题和解决方案的部分可以帮助开发者解决在使用过程中遇到的问题。 - **扩展与定制**:介绍如何扩展NBear的功能,如自定义拦截器、日志系统等,以满足项目的特殊需求。 总的来说,NBearV3.7.2...

    快速开发框架设计NBear V3.3.9 Stable

    NBear原名Ilungasoft Framework,是主要有Teddy开发的一个基于.Net 2.0 (C# 2.0, ASP.NET 2.0)的快速开发框架,她将使您基于.Net 2.0的web/winform/distributed开发变得异常高效、性能卓越。

    ASP.NET源码——[论坛社区]NBear+NBear开发BBS系统源码.zip

    【ASP.NET源码——[论坛社区]NBear+NBear开发BBS系统源码.zip】是一个包含使用ASP.NET技术和NBear ORM框架开发的论坛社区系统的完整源代码包。这个源码示例对于学习和理解ASP.NET web应用程序设计,以及如何利用...

    asp.net 优秀框架NBearV3.5.6_binary

    而NBear则是.NET平台上的一款优秀的开源对象关系映射(ORM)框架,它的全称为Non-Block Entity Access Repository,由陈宝权(Bob Chen)开发。NBearV3.5.6是该框架的一个版本,其Binary版本通常包含了编译后的二...

Global site tag (gtag.js) - Google Analytics