re: 用asp.net mvc写一个后台文件上传 maple0112 2009-06-20 11:30
--引用--------------------------------------------------
向世界出发: 能上传2G的文件吗?Silverlight就可以,很强悍。
--------------------------------------------------------
用web来传2G的文件,实在是难忘它了
“虽然ADO.NET EF提供了获取组合属性的能力,但不能处理多层次,并且不能对加载过程进行控制。”
不太明白这句话的意思,楼主能解释下 吗?谢谢!
@brightwang
我想知道 “在hibernate上不存在外键显示调用load”,那么如果一个user包含很多orders时,他是怎么取的?数据量大的话,他是怎么解决的,谢谢!
@思考-总结
---由于目前的项目小,暂时放弃考虑这个问题,基本上是采用esql来实现,将返回的DbDataRecord转换成DataTable来使用。代价就是Linq的后期绑定行为丧失殆尽,同时Linq的函数的组合性也被放弃了。
----------------------------
你这和用以前的ado.net方式一样,那还用EF做什么?
1 Context都一致从ContextManage来获取,不管是DAL层,还是BLL层,或者VIEW层也好。 所以最终把ContextManage放到了Model层。但是其实最终的Context的获取,肯定是从HttpContext.Current.Items获取回来的。
如果需要测试,可以将ContextManage写成接口,在web项目中,ContextManage的实现是从HttpContext.Current.Items来获取的, 而测试项目中,可以ContextManage的实现写成单例或者线程单例。
2 PO<-->BO<-->VO 的转化问题。
由于目前的项目小,暂时放弃考虑这个问题,基本上是采用esql来实现,将返回的DbDataRecord转换成DataTable来使用。代价就是Linq的后期绑定行为丧失殆尽,同时Linq的函数的组合性也被放弃了。
如果有人也想像我们这样干的话,有一点要记住,如果查询返回的是一个Model的集合的话,转化DataTable的时候会报错。EF会自动把返回的结果转化成一个List<T> 这样的对象集合,而不是DbDataRecord,不知道算不算EF的一个Bug.
3 业务逻辑,我们由于采用ContextManage来管理Context,所以最终还是把业务逻辑放到了BLL中去。
以上是我的一些不成熟的意见,盼LZ回复。
我们也正在拿这个做测试的项目,关于同一个请求中复用的问题,看了一段国外的代码,基本原理就是写一个ContextManage,获取EF中的ObjectContext都从这个Manage获取,
Manage获取的代码,主要是把在当前请求中的Context放到 HttpContext.Current.Items中去。
但是需要自己写一个HttpModule 来释放 HttpContext.Current.Items 中的Catch。
我们最后的分层体系,还是按照三层来分,DAL,BLL,View
目前遇到的问题,
1 DAL中的通用Save方法
每次都要先Load,后SaveChange,代码大概如下:
public virtual int Update(T t)
{
int result = 0;
GTIMediaEntities context = ManageObjectContext.GetContext;
EntityObject eobject = (EntityObject)context.GetObjectByKey(t.EntityKey);
//context.Attach(eobject);
context.ApplyPropertyChanges(eobject.EntityKey.EntitySetName,t);
result = context.SaveChanges();
return result;
}
如果有什么好的解决方案,请赐教。
2 BLL层几乎没有什么代码,因为项目简单,而且比较小。
解决方案
public IBLL
{
private IDAL dal;
[Dependency]
public IDAL DAL
{
get
{
return this.dal;
}
set
{
this.dal = value;//为了方便使用Unity,才写的set属性,否则get就可以了。
}
}
}
这样如果在BLL中没有业务逻辑,只是简单的DAL调用的话,就不需要写额外的代码了。
比如在页面直接可以这样 AddProdudct:
Product p = new Product ();
BLL bll = new BLL();
bll.DAL.Add( p);
但是以上结构,是否合理,还请各位高手赐教。
其实这些上下文的处理方法可以参考hibernate,人家几年前就提出了open session in view,《NHibernate in action》里面也有介绍过.net下的用法,而且还特地给NHibernate留了一个绑定到上下文的方法,毕竟EF和hibernate还是比较相似。
还有泛型DAO,EF的实现比起Hibernate的实现要丑陋很多。
--引用--------------------------------------------------
Anytao: 呵呵,我也很关注,这个系列我也有很多想法,准备在《一步一步MVC》中慢慢挖据。
关于EF,令人头痛的是对于外键属性的Load处理,一直没有更好的解决方案。BLL层获取数据的代码变得非常难看。
不过,保持ObjectContext和HttpContext相同的生命周期是非常好的思路,能够兼容上下文处理的很多弊病。
继续关注
--------------------------------------------------------
这个用过hibernate的人都知道--open session in view,可是淮橘为枳,在hibernate上不存在外键显示调用load()的方法,所以在EF里面这样用还是很不爽的,include太多,显示的load,这些都导致方法复用不好。
呵呵,我也很关注,这个系列我也有很多想法,准备在《一步一步MVC》中慢慢挖据。
关于EF,令人头痛的是对于外键属性的Load处理,一直没有更好的解决方案。BLL层获取数据的代码变得非常难看。
不过,保持ObjectContext和HttpContext相同的生命周期是非常好的思路,能够兼容上下文处理的很多弊病。
继续关注
@书生多命贱
不能修改映射文件吗?
这个还真没有尝试过,对于ef现在确实还是浅尝辄止,所以还要多学习。
@双鱼座
期待双鱼老大的后续文章。
@xiao_p(未登陆)
你说的这种方法我用过,不过会有问题,自己加的属性在ADO.NET EF 里用不了!说是这个属性没有和数据库里对应,大概就是这样!
@书生多命贱
分页的问题我后面的文章会讲到,事实上这也是使用二次Model的一个原因之一。
SQL写代码的确不错。个人认为有两个问题无法回避,一个是重构,使用Linq可以在设计时发现所有的错误,而SQL不行。另一个是大量使用的聚合,ADO.NET EF一行代码几乎都帮你做好了,SQL你得写一堆。
@xiao_p(未登陆)
ADO.NET EF的问题我后面一篇就会讲到。其实EF的运行时是非常稳定可靠的,性能也非常好。虽然有些查询会返回“不支持”,相信后面的版本会有改进。问题是出在建模、映射等设计时。坦率讲,那个DSL相当的糟糕,我现在是凑合着使用而已,苦于没有时间,要不然我真的要自己写代码换掉它。
你在new一个EF上下文的时候的确不会建立数据库连接。但是你建立EF上下文的目的不正是使用数据库连接么。
ASP.NET MVC的View最好不要访问EF的上下文,这一点“书生多命贱”已经讲了,是出于解耦和单元测试的需要。尽量让View更单纯一些比较好。
@书生多命贱
直接弄个partial class 然后在里面对project 进行扩展,价格username属性,就ok了。
这样既不破坏代码生成器弄出来的代码,又扩展了project model,感觉还是挺不错的。
我明白你的意思,但是,弄出来就几个model有的时候就是有抵触,虽然这种抵触未必有道理。人都是有执念的吗。。。 呵呵
@xiao_p(未登陆)
如果联表呢?Project 包含userid,现在我要显示所有的project,并且显示username,这样,你用ADO.NET EF 的model就不行了,必需自己写一个实体来实现;或者直接在前台在linq语句,那样就没有分层的概念了!!!
@书生多命贱
恩,也想过这样的解决方案,但是想到很多同样的model,要被生成两次,心里面就不舒服。所以,宁可将object context拉到客户端来用,不解藕了。让它跨层,虽然不是很好的设计,但是,确实够方便。
@xiao_p(未登陆)
我觉得 用 二次Model 挺好,挺通用,至少ui的部分和 ADO.NET EF解耦了,高层实现也不用关心底层用什么操作数据库的
对于ef 现在还是浅尝辄止。希望能多看到点双鱼老大关于这方面的文章。
object context 感觉有点持久层的意思,也看见过同事用享元模式统一管理object context的生命周期,不过客户端是winform的。
另外,我通过用refelector看过object context的源码发现,object context的生命周期和数据库连接无关,只是在save changes和select的时候才打开数据库连接。同样的,new很多个object context,数据库的连接数并未增加,也可以看出这点。
目前,对于如何保持object context的生命周期现在还没有好的办法,双鱼老大的做法还没有尝试过,回头尝试看看。
另外,就是如果对于多层开发,将dao层单独的独立出来,而object context只能被dao 和业务层调用,不能被ui 调用的时候,会有一定的麻烦,不知道双鱼老大是如何解决这样的问题的,因为如果缺少了object context的持久层支持的话,有些地方开发会有一些麻烦。比如更新的时候,可能要重新取得对象,想知道双鱼老大是通过区分model的方式解决的吗?
我举个例子,一个people包含很多个order, 如果orders很多,涉及到分页呢?我觉得都不太好解决!
如果一个对象关联的对象太多,那么用ADO.NET EF更新这个对象的时候,对数据库的操作也就很多,性能上,编码上好像都蛮烦的,至少给我的感觉是这样。
直接sql语句的好处我觉得是快,编码的速度快,sql的执行也快。谢谢
@Q.Lee.lulu
维护这些对象是不可避免的。不过这些对象粒度非常小,维护起来非常简单,可以直接使用C#3.0的初始化构造器。请留意此文的后续文档,结合实例解释二次Model的意义和维护方法。
@书生多命贱
HttpContext 的Items 和 Cache有什么不同,请查阅MSDN相关文档:
System.Web.HttpContext.Items的定义:
(
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.items.aspx)
Gets a key/value collection that can be used to organize and share data between an IHttpModule interface and an IHttpHandler interface during an HTTP request.
System.Web.HttpContext.Cache的定义:
(
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.cache.aspx)
Gets the Cache object for the current application domain.
本文仅仅讨论ADO.NET EF,直接写SQL语句好在哪我不知道,不在本文讨论范围,那应该是另外一篇文章的事情。不过可以肯定的是:二次Model的功能不是一个平面式的DataTable可以替代的,除非你用一个带关系的DataSet。
把对象放到HttpContext 的Items 和 Cache有什么不同?
Cache会存在一段时间,Items只是在一个请求里面??那应用场景呢?
如果ADO.NET EF更新一条Project,并且关联了一个user的话,更新的时候是要把这2条记录都取出来,才能更新。
维护二次Model,其实这样我真的不觉得比我直接写sql语句返回datatable好在哪?好在oo吗?
关注!!
大量的二次Model和Form Model维护起来会不会是噩梦 ?
re: ORM之硬伤 晴天彩虹 2009-04-10 10:16
这文章太棒了,讨论的东西永远不过时啊,收藏
太好了,我昨天在家还在想MVC上传怎么样做的好点,楼主今天就写了个
貌似特地为我写的啊,呵呵
能上传2G的文件吗?Silverlight就可以,很强悍。
@Jeffrey Zhao
呃……我觉得实现代价大了点……我还是暂时不考虑这么强悍的上传功能,有就行了……
re: 用asp.net mvc写一个后台文件上传 Jeffrey Zhao 2009-03-29 21:41
@JimLiu
目前解决方案都是些通过客户端和服务器端交互的trick,没多大意思,个人认为。
@JimLiu
网上有很多ajax upload组件,通过重写httpmodel+requestwork来实现的.
--引用--------------------------------------------------
henry: Ajax上传加上进度处理要重写的东西太多了...
说实话用flex等东西写一个成本上节省很多.
--------------------------------------------------------
js的能有办法显示进度?有资料吗?介绍一下
Ajax上传加上进度处理要重写的东西太多了...
说实话用flex等东西写一个成本上节省很多.
--引用--------------------------------------------------
Jeffrey Zhao: @JimLiu
or flash/silverlight
--------------------------------------------------------
用navite的东西,要求就要高多啦!起码能有多文件,显示进度的嘛,哈哈~
re: 用asp.net mvc写一个后台文件上传 Jeffrey Zhao 2009-03-29 19:39
@JimLiu
or flash/silverlight
无刷新上传好像目前只能用隐藏iframe的说……
我也做过一个,实际上实现还是比较简单的。
re: 用asp.net mvc写一个后台文件上传 Jeffrey Zhao 2009-03-29 18:42
第二句话,应该和JavaScriptResult没有什么关系,是客户端处理的问题。
用fiddler看看就都明白了。
re: ORM之硬伤 冰の酷龙 2009-03-07 11:05
mark,好动东西不标记一下,以后就找不到了。
re: ORM之硬伤 todd zhao 2009-02-13 08:52
新手 受教!!!
re: ORM之硬伤 Raze911 2009-01-05 15:44
@阿水
--引用--------------------------------------------------
阿水: 哈哈 讨论了很多了来一个 业务吧,也是我们项目中实际的功能。<br>一个医药配送中心管理系统。中有这样一个业务(客户提出,设计时没有)<br>仓库里的药品损益不直接修改库存,而是到另一个库存里(异常库存)<br>比如 报损10 那么 异常库存里就是-10 ,报益为正数。<br>现在 说异常库存里 有很多记录,有正有负。现在的要求是 <br>把商品编号相同,但是批号不同的记录。数量能够正负抵消的<br>记录,生成一张单据。单据明细记录格式如下 <br>编号 批号 数量 <br>a 1 10<br>a 2 -10<br>......<br>希望大家能,给与我一些指导。我当时写这个功能<br>用PLSQL 写了 230行,声明了3个游标。
--------------------------------------------------------
这个功能,你写了230行的PLSQL
可是如果用D2006里的EcoIII来实现的话,好象基本上不需要写多少代码的吧
整个功能需求分析了一下,大家可以在EcoSpace中画4个类
1、事物(抽象类):
属性1:编号(interger)
2、药品记录(抽象类):继承于“事物”
属性1:药品(值源自“药品”类实例的“编号”属性值)
属性2:批号(interger)
属性3: 数量(interger)
3、药品(实体类):继承于“事物”
属性1:名称(string)
4、盘库损益记录(实体类):继承于“药品记录”
在窗体中将对象信息表达式控件(EH)的OCL表达式设为
"盘库损益记录.allinstances -> select(药品 = VH)"
这个OCL表达式表示----在全部盘库损益记录的实例中取得药品编号等于VH的实例集合(VH是动态参数控件决定的动态参数)
这样基本上就完成你想要的结果了
ECO是自动ORM的,也就是说以上功能完成后,如果你希望输入的数据能持久化,那么加个数据库映射控件就可以了,你想挂DB2也行,挂ACCESS也行,挂ORACL也行,挂SQLSERVER也行
你用230行PLSQL完成的东西,ECO里只是画4个长方形(4个类),定义一下4个类的关系,再对几个控件的属性进行适当设置,手工代码好象不用超过10行,就完成了
对ECO不熟悉的人或许要比较久才能搞清控件怎么才能正确设置,你对SQL很熟悉,可能最终完成速度比用ECO但很不熟悉的人更快,这个我不否认
但问题是其它人看ECO的结果应该很简单明了吧,要修改也比较简单吧
别人看你的230行代码是不是会比较头痛??要修改的话是不是更头痛??
你用的PLSQL是跟ORACLE产品相关的,ECO完成的结果跟任何数据库产品都不相关,在ECO框架里搞出这个结果可以打了包到处复用,可以挂任意数据库产品,你那230行代码送给别人,别人敢随便用吗??如果别人用的数据库是ACCESS呢??
re: ORM之硬伤 Raze911 2009-01-05 11:16
我是个初学者,本身为业务人员(会计),正在学习ECO
自己做了个案例,感觉好傻瓜化的
就是
1、自己根据一个现实需求进行分析需要管理的实体类与抽象类,以及各个类之间的关系,在ECO框架中画了个ER图
2、在收集对象信息的控件(我称之为对象信息集控件,类似于数据集控件的东西)中用OCL语言收集ER图中的对象信息(可以是基础信息也可以是派生信息)
3、将界面控件与对象信息集控件相关联
4、因为DATAGRID有一个----不能在新增一个对象实例时将指针自动指到新增行上的----问题,所以用了两个TIMER控件各一行代码来解决这个问题
5、以上工作完成,运行程序测试业务逻辑正确,符合要求
6、返回设计界面,在ECO框架中加上数据持久化控件,自动生成数据库结构(也可以先选择用XML文件保存数据,待整个项目完成后再改挂所需采用的数据库产品)
7、结束
全部过程我只写了两行代码(就是第4点中的两行代码),涉及9个类,其中4个类之间有相互的角色关联关系
照这种开发模式,完全可以由业务人员(比如我)去学习UML,在ECO框架里画好ER图跟状态图,自动生成代码框架,然后细节要求由正经的程序员来完成
这种模式不好吗?
re: ORM漫谈 xjb 2008-12-05 17:21
请问你的Kanas.net Framwork 2.0版本进展如何,我一直关注呢
re: ORM漫谈 xjb 2008-12-05 17:16
双鱼的文章都很有深度
re: ORM漫谈 碧落 2008-12-03 19:35
@巫云
我们公司是使用存储过程来隔离T和O,同时使用存储过程解决T和O的差异。
re: ORM漫谈 双鱼座 2008-12-03 08:48
@xiao_p
多谢褒奖,牛人实在是不敢当,汗...
@巫云
我也曾尝试过把数据库和业务层分开,但是没有成功。有什么经验可以分享?
@Anytao
俺一直在啊,只是平时瞎忙,显得有些手懒,惭愧...
@包建强
深感荣幸!
re: ORM漫谈 包建强 2008-12-02 23:27
老兄,
精华集的CLR分册开始,你有文章入选,
请加我MSN:bjq_ren@hotmail.com
re: ORM漫谈 杨义金 2008-12-02 19:59
支持楼主,同意见解!
re: ORM漫谈 Anytao 2008-12-02 12:16
双鱼座的回归?
re: ORM漫谈 巫云 2008-12-02 11:38
一直有个问题,就是一个O应该对应数据库里几个T,什么样的T?所以即使从O下手,也很麻烦。感觉还是应该职责明确,把数据库包装成透明的接口,建数据结构,提供数据的事,交给DBA来做,这样再提供一个透明的数据层来跟O做交互,会简单一些。
re: ORM漫谈 xiao_p 2008-12-02 10:15
* 必须一切从模型开始,无论你是UML也罢,ER也罢,都可以。有Modeling GUI也好,没有的话Hosting一个Addin到IDE也行。
* 必须有自动代码生成,并且既能生成api代码,也能生成sql脚本。当你的数据模型变化以后,改完model,你只需要按几个键,然后所有的一切都有工具帮你搞定(当然包括数据库结构重定义和测试数据自动导入)。
* 功能上必须提供足够的数据操作,性能可靠。必须支持引用、继承和关联三种关系,且继承关系必须是一表一类。
* 除了能传递数据,还必须能够传递“条件包”,当然,运行时的东东,可以是linq的expression也可以是hibernate的criteria。这是分层操作和分布式操作所必须的。
* 虽然通用的方式是以实体为类型、数据行为实例,也可以是以实体为组件(component),而隐含行,但需要确保引用、继承和关联关系。
这几点完全的体现了orm的关键,lz不愧是偶在博客园最早关注的“牛人”之一啊!