浏览模式: 普通 | 列表
1

数据同步订阅的注意事项

[ 2006-05-29 11:48:34 | 作者: progame ]
1、当你可以顺利建立订阅,但是在初始化同步时总是报错:
Error info : number 14010

Full error message : The remote server is not defined as a subscription
server.

那么你首先要查的就是
select @@servername
select SERVERPROPERTY('ServerName')

如果发现不一致,那么就
sp_dropserver 'old_name'
go
sp_addserver 'new_name', 'local'
go

2、如果初始化同步时总提报错说
Error: "The process could not make a generation at the 'Subscriber'

The merge process
timed out while executing a query.Reconfigure the
QueryTimeout parameter and retry the operation

然后你跑到run agent的property中加上 -QueryTimerout 10000
再试 结果还是这个错误的话

那么你就应该试试,重启subscriber的server服务了
因为很有可能有未释放的死锁或进程访问导致无法合并复制无法更新表结构

3、当碰到这个错误时
The agent is suspect. No response within last 10 minutes.

这个表示agent无法忍受这么慢的反应了[code]Just right click the Replication Monitor node, click Refresh Rate
and Settings, and then increase the Inactivity Threshold values.

4、清除订阅端的meta date
EXECUTE [TEST_B].dbo.sp_mergesubscription_cleanup
[/code]...

阅读全文...

对象化查询之OCL vs. OPath

[ 2006-05-06 00:23:29 | 作者: progame ]

(同样是存档用)

令人心动的对象化查询

对象化查询是O/R Mapping中非常让人心动的一个特性,当所有的表对我们来说不复存在后,我们可以对实体进行CRUD,可是当我们需要返回多个实体的结果集时,我们怎么办呢?Dataset做为载体是必然的,可是我们查询过滤数据的方式是怎样的?sqlNo!我们就是在尽量避免直接使用sql,因为sql不便于重构,可移植性太差,拼凑出来的sql语句对测试覆盖率也有影响。所以大家都期待着可以用对象化查询来根除将Entity再当做Table来处理的尴尬。

.Net下的O/R Mapper对对象化查询的支持

目前为止,.Net下的O/R Mapper对对象化查询的支持绝大部分都是非常有限的:NHibernate用的是HQL语句,其本质可以说是一种把Entity看做Table的改装后的sql语句,DataObjects.NetNHibernate差不多,也有一套自己的类sql对象化查询语法,其它很多O/R Mapper使用的是简单的属性过滤查询,而说到对对象化查询支持得最强大的,要算ECOⅡ和ObjectSpaces,前者使用的是OCL语法,后者是OPath

OCL起源

OCLOMG组织制订的UML语言规范的一部分,它的初衷是用来对UML模型视图中的Object添加约束描述的,并不是一种编程语言,而OCL应用到O/R Mapping中就俨然成了一种对对象进行查询的语言(OQL)。

OPath起源

OPathMS提出的在WinFS中准备大量使用的一种对象查询语言,从它的命名上可以看出和XPath的相似之处,MS的口号一直是把复杂的东西变简单,把简单的东西变成自动化。所以这个OPath确实不可小觑。

简单的例子

先我们从一个简单的例子入手,假设有如下的实体关系(画图太麻烦,还浪费空间):

Department (code name employees)

Employee(code name department salary)

查询

OCL

OPath

包含薪水大于3000的员工所有部门

Department.allInstances->select(self.employees.includes(salary > 3000))

Exists(employees[saleary > 3000])

得到部门001的所有员工

Employee.allInstances->select(self.department.code = ‘001’)

Department.code = ‘001’

所有员工薪水都大于3000的部门

Department.allInstances->select(self.employees.forAll(salary > 3000))

不支持

员工最高薪水大于3000的部门

Department.allInstances->select(self.employees.includes(salary > 3000))

不支持

功能比较

从这个列表中可以看到OPath的语法要简洁得多,但OCL的集合操纵能力却是OPath无法比拟的,下面是OCL的一些集合函数:

名称

功能

Collect

得到一个属性的集合

Exists

如果存在符合条件的元素为真

forAll

只有所有集合元素符合条件时才为真

Includes

是否包含某个对象

Select

获取符合条件的一个子集

Reject

减去符合条件的一个子集

IsEmpty

集合为空

NotEmpty

集合不为空

此外,ECOⅡ对集合操作还有增强,如提供了sumavgmaxmin的聚集操作函数,同时它还支持多种非聚集函数,如concatlengthtouppertolower等。

其它的一些特性:

特性

OCL

OPath

NULL判断

支持

支持

Implies(表示如果左边为真,那么右边也要为真)

支持

A implies B可以转化为(A and B) or (Not A)

类型判断和转换

支持

Distinct

支持(通过Set集合返回)

不支持(因为只是对象获取和属性过滤,没有集合操作,所以不涉及到子集合,而外部对象集合一般有主键约束)

集合内元素获取

支持

不支持

Order By

支持

不支持,但可以通过调用查询对象的方法达到目的

假如增强OPath的话,大概会是什么样子?

如果要支持集合操作的话,那么现有的OPath语法的简单性肯定要大打折扣,比如说类似于OCL中的forAllOPath如果要实现的话,可能的方法就是:

(Employees[salary > 3000].Count = Employees.Count)

性能比较

因为现在ObjectSpaces中的OPath语句最后都将转为SQL执行,所以它的性能是非常好的(时这也正是它功能无法强大的弱点),而OCL的语法只有部分才能转化为SQL,因此在ECOⅡ中,还有部门的OCL操作必须针对内存对象来进行,这样也就使得必须装载大量的实体对象到内存中。

你将选择哪种查询?

就我个人而言,我倾向于增强型的OPath。毕竟更加复杂的查询我们可以通过viewstore procedure来完成,就算OCL再强大,也无法涵盖我们需要的查询功能,其内存对象操纵的性能问题不能不让我们谨慎使用,而ECOⅡ可以算是一个MDA的框架,这也让我对MDA的将来感到一些担忧,除非ANSI SQL进化到了可以更加强大的地步,各数据库本身就可以完成OCL所需要的查询功能,但这个时候,也许SQL的表达更加直观,那么,我们又为什么需要OCL来查询呢。当然,OCLUML中的作用我们并不否定,只是直接从模型生成代码的应用似乎只能在不太复杂的场合才生效。

(注:因为ECOⅡ的资料很少,很多是参考它的前身bold for delphi的语法,而OPath的资料也少,很多都是无关痛痒的简单操作,这让人弄不明白到底是它的语法就这么简单还是另有其它的增强。)

我需要什么样的ORM(对象持久层)

[ 2006-05-04 21:48:27 | 作者: progame ]
首先声明,标题中是“我”,不是“我们”,别人希望如何我不太能够帮着下结论。

一个可以打动我的持久化层(Persistence Layer)或者说OR/M(Object Relateion Mapping)应该具备哪些特征呢?

1、简单,尽可能地简单
没必要为了我偶尔用到的功能花费太多的精力,CRUD满足之后,关于Relation如何处理的问题,我觉得尽可以不必那么讲究,一定要那么OO吗? 一定要 order.items这样去访问order的明细吗? 我觉得太可不必,为了实现这种功能,一是我必须再设计Entity类,以决定有哪些OnetoOne、OnetoMany, ManytoMany的关系,然后会定义一个类似这样的很OO的class出来:
class order
{
  .....
  customer _customer;
  entitylist<orderline> _items;
}

看上去真的很帅,但是我必须去维护它,因为不是所有的关系都需要这样定义,lazy loading并不能让人就可以放肆地定义一个很“胖”的类出来。

如果有人说我可以先class,再使用schema工具生成数据库,那么很不幸,我们没有共同语言了,起码我现在对这种方式不感兴趣,而且我也从来不这样做,像如何让union all构造出来的view利用到索引里所说的一样,我会因为数据库增加一些不相关的列,也会因为性能而再增设冗余,用class的方式去思考的话,我很难知道最终的数据库要做多少修改。如果仍然用“表”的方式去先构建“类”,那么我觉得这是一种掩耳盗铃的行为。顺便说一句,我暂时对domain object还不是很感兴趣。entity就是用来存储数据的,其它的事千万别让它去承担。

那么我希望如何处理relation呢? 非常简单:
entitylist<orderline> items = pl.getList(order, typeof(orderline));

那么如何生成filter呢? 命名规则+代码生成,用order的主键id的值,以及用orderline的order_id列,构造select ... from orderline where order_id = order.id

2、透明,让我知道所发生的一切
  
我不希望在保存一个或一组entity时,会发生我并不知道的级联更新,或者有些认为我没有dirty flag而不做任何更新,因为有时候一个update t set f = f 并不是什么活都不干的,当我要retrieve时,别因为缓存中已经有了就不从数据库加载了,因为可能我确实需要最新的数据,或者把数据缓存而不提交,这样我的另一个client会因此而无法即时获取数据,数据库的连接也要让我知道,是使用了连接池还是立即释放掉了,什么时候会开启事务,什么时候会提交事务,这些,我统统要知道。

有人会有意见了,ORM不就是为了隔离数据库么,你要知道那么多鸡毛蒜皮的小事干什么?

我只能说,这些东西如果我不知道,那么我就很难写出对数据库优化的处理。而需要这个的话,仅仅是可以trace generated sql是不够的,我希望是当告诉持久层去买烟时,它不要很机灵地顺便买个打火机回来,尽管很多时候这个机灵是很讨好的,但有时候可能会因此给我带好不必要的麻烦。

这里透明的意义就是可控性,当我要它做的时候再去做。

3、可测试性,减少重构或者维护的工作量

这个重要了,假如说我要构造一个查询,怎么办? criteria.add(a.ID like 'a',LogicOperator.ADD)? 这种方法又似乎很OO了,但是当要构造一个
(a and((b or c) and c)这样的条件时,写出来的语法可能连你自己都搞不清楚之间的关系了, 而且如果再加上join,再加上select fileds,会是什么样子?相当于原来SQL的语法树了,假如再来一些,计算列,case 判断,group,having,order by, exists... 天啊,受不了,还是用VIEW吧,可是view还得处理filter的问题,那么,换做Store procedure吧,传递的参数怎么办?用
(@a is null or a = @a)这样么? 再定义那些parameters,这个SP写得就比较难看了,再多来点if else的处理吧,SQL脚本就更长了...

一个查询或者复杂的更新,如何是最易于理解的? 就是SQL,要用对象化来转述它,只能让人看得云里雾里,ORM要不要去处理这些事情?我觉得要。但是就是最后的实现方式一易于理解,二要可验证是否正确,三要易于维护。

用cirteria构造,难于理解,也无法完全验证;用SP,难于维护,当加一个filter时,又要去修改sp对应的CLASS,如果不用sp<->class,那么关于参数的验证又无法保证了,因为可能有个地方你调用了exec sp @a,@b,@c,但后来这个SP可能参数定义,参数位置,参数个数都改变了,原来的调用就隐藏了一个BUG了,如果测试做得足够好的话当然没话说,但你真能做到100%的覆盖用例?要知道还有大量的if else存在。

那么我现在是如何做的呢?很简单,将SQL定义和代码分离,你放哪都行,怎么加密随便你,SQL的写法是这样的:
select a,b,c from t where #x# and #y# or z = :z

#x#是一个filter,当没有fitler定义给它时,它会用1=1替换,:z是参数。
这样有什么好处? 首先这条语句是可检验,当我用xml同样定义了filter后,我可以将对应的filter替换,并用相应的值替换:z,然后我就得到一个完整的SQL语句,这个SQL是可以提交到数据库去检验的。那么如何设置参数的实际值呢? 还是通过命名规则来映射,这个值会来自我程序内部维护的一个data store。

4、性能,瓶颈不能发生在这个地方

虽然说数据库执行SQL的时间会远大于ORM层处理和生成SQL的时间,但我的要求就是生成的SQL千万不要和手写SQL相差太多,对于批量的操作,一定要尽可能地快,有些批量的更新要给我一种特殊的操作,比如说对order的所有items设置一个flag,就没必要让我去遍历list,再一个个设置,再提交了,让我在一行代码写完这个处理,并且生成update orderline set flag = 1 where orderid = @id这样的SQL。

而这点和第2点有点重合了,只有当可控性强了之后,才有可能去避免性能问题。

那么对于集合操作呢? 我永远不需要items[3]这样去访问第3条数据,我永远不会加载一批数据,却只为了修改其中的几个,也就是说order.items对我来说没有意义,我会如何操纵这些集合数据呢?

大概是这样的:
C(create):
list = new list();
list.add(item);
pl.addUpdatetoQueue(order);
...

阅读全文...
分类: ORM相关 | 评论: 1 | 浏览: 3829

Web HTML Editor从 widgEditor 修改而来,加入了undo redo的功能

google 的 page creator应该也是从widgEditor修改过来的,这个编辑器的特点就是:is an easily installed, easily customisable WYSIWYG editor for simple content. It replaces existing textareas with an improved editing pane using JavaScript. 很容易添加到现有应用中来,并且代码规范,容易修改,而且生成的HTML也是符合标准的(其实也没几个是它生成的,才那么两个按钮,实在是有点不够用)。

Syntax Highlighter使用的是dp.SyntaxHighlighter ,它是完全javascript客户端实现的,并且使用css进行控制显示,这样可以只保存内容。

下面是一个演示:

1public?Field?Field(string?name) ?
2{ ?
3????if?(!m_Fields.Contains(name.ToLower())) ?
4????{ ?
5????????return?null; ?
6?
7????????System.Text.StringBuilder?sb?=?new?System.Text.StringBuilder(); ?
8????????sb.Append("?table:"?+?this.Name); ?
9????????sb.Append("?field:"?+?name); ?
10????????sb.Append("?current?field?count:"?+?this.m_Fields.Count.ToString()); ?
11?
12????????throw?new?System.Exception(sb.ToString()); ?
13????} ?
14????return?m_Fields[name.ToLower()]?as?Field; ?
15}?

但是代码高亮后的HTML庞大了很多,又看了其它的几个类似的加亮的,都有同样的问题,我自己还是用习惯UBB编辑器。

1