2008年3月27日
#
故事角色:
外围公司,势力雄厚,境外公司。
温某,31 岁,广东人氏,工作热情,责任心强,数据编辑员出身,口才好,家里条件可以,家买住房一套,开二手四轮车。
邢某,20 岁,河南人氏,一技术精英,擅长 web 开发、数据库优化,开发能力特强。缺点:交际。
我,20 岁,湖北人,技术还行,擅长 web 开发,数据库优化。缺点:交际。
三人是旧同事。
故事背景:
邢某于 06 年研究足球外围投注网站(外围公司)时发现漏洞,故此认识该公司高层。之后邢某找到我谈了相关情况,说一起和外围公司谈谈业务,看有什么好的项目可以做。我俩的口才都不行,于是我力挺温某加入,温某加入前还在工作,在工作之余时间我们一起和外围公司进行 skype 交流。大概进行了 1 个月时间,在邢某的关系下,我们比较顺利的拿下这个项目。其间,我和邢某都是坐温某的车来来回回去一些地方(周末),温某认为他自己都可以接到这个项目,他说他月拿得少于 1A 都不想干。之后又说三人合伙发展公司,口头协议股份,谁知项目未开始,争论就从股份的数目开始了,在我现在看来完全是温某的计谋,他头顶头发不多,相信是较聪明之人,如果公司内同时存在两技术,他就不可能什么都可以话事做主。在项目外包合同签完后邢某就离开了,合同内写明温某独资 10A 成立有限公司,并以公司的名义与外围公司签完合同。跟着温某火速辞职,因为他有了新的希望。
收到收围公司给的第一笔开发款后,租办公点,买公司用品、电脑、冰箱、微锅炉等等,在 07.05.01 号请他全家人来公司搞庆祝,此时我好像已经不是公司的股东了。东搞西搞,我还没来得及拿第一个月的工资就已经将公款用完。
到了第二个月,外围公司按合同初稿写明理应支付此月的开发费用,但由于邢某的离开被外围公司知道后,就一直在拖款。直到工作到第 50 天,温某实在按耐不住了,但还得发工资的,就算不发我,也要发另外一个做美工的(另一个以前的旧同事)。虽然极度不高兴,还常把这种情绪带到工作和表情上。
之后的 4 个月,它一直在掏自己的腰包,也就是拿公司注册资金来发工资的。直到外围公司对我们的工作成绩给予回应时,公司好像有了救星,外围公司把尾款打给了我们公司。那个月的工资发得很及时(掏它自己腰包时要死不活,不是的话就很爽快。我一开始还没怎么知道它是这样的底气)。
公司还算稳定,一直发展到今年。我去年明明可以大搞一票的,最后却只拿了个工资,而且比以前还少。其实我要求并不高,月薪过 8K 就满足了。为了这份工,我得罪了好几个人,丢了两份兼职。按照公司的发展方向,我还要等好几年才能有出路。最重要的一点是我已经不认同温某的决策,所以经常会有争吵。虽然只有半年多一点时间发展,但温某的决策错过很严重一次是花了很大的心思和人力去做的一个用户不关心的功能,用了三个月开发周期。
最后我提出要离开,跟着是清算分公司资产。由于之前公司的财务全由温某一人管理,公司进出账在它个人银行卡,公司模式为有限公司(不是合伙和股份有限公司),所以现在清算资产时会有很多问题,也就是账目不对。扯了半个月,大家都很激动和冲动,在清算账目时他对另一个人背后直接骂我。
都不是好惹的。
怎么说也有几十万财产,他总说自己多君子,没有对不起公司什么时,我实在挡不住那股气愤,在我看来是个十足的伪君子。直到我和它说小人背后人身攻击我时,它说什么也不肯分钱给我了。我也没有办法,顶多知道它是什么人,让它以前同事知道它是什么人。我还能说什么?中国的法律只能这样,而他和我说清算公司财产也只是出于是旧同事的份上才会这样,换了是第二种关系,谈都没得谈。我不知如何形容当时情况,反正是很复杂,就看你倾向哪边去想。
公司名:广州市数威网络科技有限公司
登记人:温某
注册金:100,000 RMB
公司地址:广州市海珠区艺影街(珠影)二期写字楼A座911室
外围公司项目:http://www.my188info.com/
公司自己网站:http://www.b310.com/
--------------------------------------------------------------------------------------
本故事发生在我身上,仅以此文献给所有技术者。
还请大家别轻信老板的甜言美语,如果说公司给你股份,除非按法律办事,否则不要相信。
已经过去几个月了,勾起我回忆的是 NicPetShop,有人说我来园子就是为了它的宣传而来。我告诉你不是,我觉得在这里可以找到更多同类的朋友,有共同的话题可以探索。
有人说我语气嚣张,我清楚,在这里和大家说不是了!我并非不可一世,而是技术者的通病(关在房子里关久了)。还请大家不在太介意。
--------------------------------------------------------------------------------------
以下引用评论回复:
@钢:
你一再的在评论中强调你的 NicPetShop 让我怀疑起你的初衷来,因为我只想讨论 ObjectDataSource 其本身而已。还有,你这个 NicPetShop 应该是全部开源,并且不存在什么商业用途吧?
如果是这样,看来是我错误的判断了你的热心,不好意思了~~ ^_^
我:
@钢
就算不开源,我也不会拿这种东西来收费,我定位方向不在技术这块,技术只是我业务实现的工具
如果认识的朋友想用我的东西,我乐意给
如果是以前公司来套我的东西,我不可能公布下载
这个以前公司是去年从零创业的公司,口头协议的股份后来我全没有,我什么也没有防备过,只是把 NicPetShop 没留给它(畜生级老板)
如果网站的 web.config 配置得太多,当要在网站下建一个虚拟目录时(比如一个独立程序,因为 www 需要与它通讯,如 ajax,所以这一定要这样架系统)。
对于这个问题,我们可以在虚拟目录下的 web.config 里 <remove 或 <clear 方法来去掉 www 下定义的值(因为虚拟目录程序无法加载相关引用或其它文件),但如果 www 下的配置极度复杂,那么我们在虚拟目录下也要相关的相部 <remove 或 <clear ??不明白 system.web.pages.controls 里为什么没有提供 <clear 或 <remove 方法,这里面添加了我常用的用户控件,最后让我找到答案:
Reflector System.Configuration.SectionInformation 不难发现以下代码:
namespace System.Configuration {
// 摘要:
// 包含配置中单个节的元信息。无法继承此类。
public sealed class SectionInformation {
//....
//
// 摘要:
// 获取或设置一个值,指示在关联的配置节中指定的设置是否是由驻留在该应用程序(关联的配置节即应用于该应用程序)子目录中的应用程序继承的。
//
// 返回结果:
// 如果此 System.Configuration.ConfigurationSection 对象中指定的设置是由子应用程序继承的,则为 true;否则为
// false。默认为 true。
public bool InheritInChildApplications { get; set; }
//....
}
}
最后我将 www 下 web.config 的 location 结点改为:
<location path="." inheritInChildApplications="false">
<system.web>
....
</system.web>
</location>
摘要: 最近出了很多 ObjectDataSource 文章,各有各的道理,都说自己的多好多好(包括我)。针对各文我都发表过我的个人看法,不知是我资历有限还是什么,没人在意我的意见。就拿 钢钢 的 《论不使用ObjectDataSource之数据绑定控件纯代码实现是否更优化? 》补记 (http://www.cnblogs.com/xugang/archive/2008/04/29/1176921.htm...
阅读全文
vss 2005 是个不错的东西,控制源码版本、多人协同开发效果还不错。我个人觉得它的亮点在 internet 连接,将 vss 服务端装在 web 服务器上,vss 可以设置文件映射到 web 网站目录,这样就避免了使用 ftp 上传文件的痛苦,不过对它是又爱又恨,我相信很多人都抱怨它的速度不是一般的慢。
针对它的 internet 慢的问题,我当时还写了一个 FileSystemWatcher 服务端和客户端程序,试图判断文件添加/变化/删除响应给服务器端做相应措施,程序比较简单,可是最后未能应用上来,因为我监视 vs.net 保存文件时会建几个临时文件(它为什么不把临时文件建去 temp 目录?),很是麻烦,最后放弃了(对公司来讲,就算做上来也没什么用,而且公司也不会专门给时间你去开发这些)。
还刻 2006 年第一次配置 vss2005,到处找文章,先是配置了个局域网的平台,使用了半个月后发现自己回家也要做公司的事,局域网根本就没办法做到(不过我见过有些人回家时把文件全 Check Out,哈哈~~~~如果第二天来的比其它同事晚的话就~~~~)。
决定试 internet 配置,先是在公司的服务器上,试了一个上午也不行,明明按步骤一步一步来的,为何会错?四处求救,可没人帮得了我~~~~同样步骤试本地,成功!试另台服务器成功!为什么就 web 服务器不行?我叼。。。决定重装 IIS,web 站点配置很多的东西,要一个个的备份才能重装(真痛苦~~~~)。。最后配置成功。。。来来回去重装 vss、御截 vss至少 5 次,重装 iis 一次。。。
这时我才明白,是默认站点的祸,公司那个叼编辑,老是抱着服务器玩,没事看文章说默认站点不安全一早就删了,我操。。
IIS 里的默认站点会影响 VSS 2005 Internet 连接,我当时新建一个空的 ip 头、名为 “默认网站”的站点也还是连不上。(这点不知道是不是真的,但最好不要删除,把目录指到没有权限的目录即可)
后来,前先配置几次也都相继出现过问题,一般是权限问题,其它步骤按网上文章来。
现在我来总结一下吧,包你百分之百能配置顺利。
环境:win server 2003 sp1 + iis 6.0 + .net 2.0 + vss 2005
1、IIS 装完后的默认站点不要删除(改名为:“默认网站(勿删)”,安全问题,将它指向到一个没有权限的目录);
2、新建 VSS 用户组;
3、新建 vss_001 用户,选择用户组为 VSS
4、新建 vss2005 目录,设置共享并设置共享权限,为允许所有(共享里的权限,不是后面的安全选项里);
5、添加 vss2005 安全 -> 添加 VSS组 允许所有权限;
6、找到 vss 的安装路径,如“
E:\Program Files\Microsoft Visual SourceSafe” ,右击属性 -> 安全 -> 添加 network service 默认权限,添加 VSS组 默认权限;
7、打开 IIS 默认网站 -> 右击
SourceSafe -> 权限 -> 添加 IIS_WPG 默认权限;
其它地方的权限为默认;
摘要: ajax 在目前 web 领域已广泛应用,其真正核心只不过是一个封装好了的 js 库。最五花八门的莫过于 asp.net 的控件,我个人认为 ajax 只是一个轻量级的东西,根本没有必要将它写成服务器组件,如 ajax.net、AjaxControlToolkit 等。所以我一直视这些组件为垃圾。。。以下说明我为什么不认同 ajax 的相关组件:1、将 ajax 封装得太死,出现问题难于调试;2、...
阅读全文
我讨厌 ViewState,喜欢 DetailsView/GridView + ObjectDataSource 做后台管理,看,这个做后台时又遇到个问题?
添加 GridView1,设置 DataSourceID="ObjectDataSource1",FIelds 里添加一个 asp:CommandField 列,ShowDeleteButton="True"
添加 ObjectDataSource1,设计时选择 BLL.* 类型,分别选择 Insert,Delete,Update,Select 控制函数
Insert,Update,Select 一切正常,没有问题发生,要有问题也一定是 EnableViewState 的值不为 True
ObjectDataSource1 里明明设置了 DeleteMethod 和 DeleteParamters,名字无误,类型无误。
反复试了几次,还是删除不了,也没有错误,单步 Debug ObjectDataSource1.OnDeleting 后发现 e.InputParameters 里的值为其它字段了,于是我想起没有设置 GridView.DataKeyNames 值,设置完后,再 F5,继续删除不了。
大家都知道 GridView 里的集成的控制都是回传过程,回传时会将 WebForm 里所有 Input 发送到服务器端验证,包括 ViewState。
HTTP Get 页面后再删除就没问题了。
ViewState 真恶心。
摘要: 见http://www.cnblogs.com/mFrog/archive/2008/04/18/1160521.html使用objectdatasource结合数据绑定控件进行简单三层架构的开发贴后感,因为我上一次没有把 NicPetShop 的这种特性显示出来,NicPetShop 对这 ObjectDataSouce 支持得很好。对于B/S架构的三层架构的开发,可能很多的人都已经了解的是比较...
阅读全文
满足一定的复杂查询,比查询 News 表里对应 News_Class 表里的 Status 值为 1
SQL 语句查询将为是:
select * from news a
inner join news_class b on b.id = a.news_class_id and b.status = 1
对于以往的 NicPetShop 来查询这个比较麻烦,一般会选择放弃 NicPetShop 的功能,直接使用 DBUtility.SqlHelper.ExecuteDataSet(sql) 后再操作,也就是最原始的方法。用 NicPetShop 的 GetItems 功能可以查出来,但性能就非常低了,如下:
List<NewsInfo> newses = News.GetItems("(select status from news_class where id = a.news_class_id) = 1", null, null);
或
List<NewsInfo> newses = News.GetItems("Exists(select status from news_class where id = a.news_class_id and status = 1)", null, null);
性能都没有 join 查询性能好
今天有想法把 NicPetShop 改造成支持 LeftJoin/RightJoin/InnerJoin 多表查询,需要考虑到以下几点:
1、采用什么样的语句查询? select * from 吗?
2、采用 * 查询会不会增加没有必要的查询返回?性能危害有多大?值不值得?
3、采用字段式选取查询,但这样会增加代码输入量,对于开发者不太方便,我已经直接放弃了这点。
4、select * from 可以返回一个很多表的横向记录,记录返回如何保存到对象中?如 NewsInfo 里的所有成员与数据表 News 一一对应,我可以增加一个 List<object> Join 来保存 Join 查询的结果?完全可以实现,但问题还是回归到了第 2 点上面。
5、我是否该放弃主表以外(即 Join 表查询到的字段)的数据吗?然后页面上还要 news.news_classInfo.Title 这样使用吗?会不会太浪费了?对开发效率和性能损耗是否平衡?
现在使用 NicPetShop 的新功能来得到这样的 List 吧:
List<NewsInfo> news = News.GetItems(new InnerJoin[] { new InnerJoin(typeof(NewsInfo), "b", "b.id = a.news_class_id AND b.status = 1") }, null, null, null);
最后执行的 SQL 语句将是:
SELECT a.[id], a.[title], a.[content], a.[create_time]
FROM [dbo].[news] a
INNER JOIN [dbo].[news_class] b ON b.id = a.[news_class_id] AND b.status = 1
欢迎大家一起讨论!
继上篇文章:http://www.cnblogs.com/kellynic/archive/2008/03/27/1125541.html
从了解 NicPetShop 内部工作方式后,对 L型 关系设计有一个全面的概念。
调用者 -> BLL -> DAL -> DataBase
循环 List<TableInfo>,如果存在 l_id 和 type INT 字段,并且 l_id 存在多个外键时(B,C表),做以下工作
1、生成扩展 IDAL/IA.cs
ABL_Info InsertB(AInfo item);
List<ABL_Info> GetItemsForB(Limit limit, string filter, string orderBy, IPager pager);
ACL_Info InsertC(AInfo item);
List<ACL_Info> GetItemsForC(Limit limit, string filter, string orderBy, IPager pager);
2、生成扩展并实现 SQLServer9DAL/A.cs
public ABL_Info InsertB(AInfo item) {
//...
}
public List<ABL_Info>
GetItemsForB(Limit limit, string filter, string orderBy, IPager pager) {
//...
}
public ACL_Info InsertC(AInfo item) {
//...
}
public List GetItemsForC(Limit limit, string filter, string orderBy, IPager pager) {
//...
}
3、生成扩展 BLL/A.cs
按原有的 NicPetShop 扩展规则,调用 IDAL 扩展的相应接口方法。
方案确定完毕,待调研后才会将此功能添加到 NicPetShop。
我的初步思路是:
数据库方面
建立 A 表 l_id 指向各个表(B,C),此表必须严格的建立 l_id 和 type int 字段,type 值初步考虑用 c# 里表名的 GetHashCode 值存储来区分(虽然不好辩认,也可能不惟一,但这样很方便就是)
IDAL, DAL 层(待完成)
Model 层
生成 AInfo.cs,同时生成相应的 L型 类
AInfo.cs
public class AInfo {
private int? _id;
private int? _l_id;
private int? _type;
private string _content;
public int? Id { get { return _id; } set { _id = value; }
public int? Relation_id { get { return _relation_id; } set { _relation_id = value; }
public int? Type { get { return _type; } set { _type = value; }
public int? Content { get { return _content; } set { _content = value; }
....
}
public class ABL_Info : AInfo {
private BInfo _bInfo;
public BInfo bInfo {
get {
if (_bInfo == null) _bInfo = System.Type.GetType("Test.BLL.B,Test.BLL").InvokeMember("GetItem", BindingFlags.InvokeMethod, null, null, new object[] { _relation_id }) as BInfo;
return _bInfo;
}
}
}
public class ACL_Info : AInfo {
private CInfo _cInfo;
public CInfo cInfo {
get {
if (_cInfo == null) _cInfo = System.Type.GetType("Test.BLL.C,Test.BLL").InvokeMember("GetItem", BindingFlags.InvokeMethod, null, null, new object[] { _relation_id }) as CInfo;
return _cInfo;
}
}
}
BLL 层
生成 A.cs,同时生成相应的 L型操作方法
public partial class A {
protected static readonly IUser dal = NicMessage.DALFactory.DataAccess.CreateA();
....
public static
}
且听下回分析……
开发分两大派,我个人喜欢直接用 SQL,但也有喜欢用 PROC 的,之前的 NicPetShop 将喜欢用 PROC 的朋友拒绝门外,结小调研后决定将 PROC 扩展成可选生成(SQL/PROC)。
昨天整理了一天,现提出下载地址:
SQL 为稳定版,PROC 需要过两天做过测试才可以放心使用。
下载地址:
NicPetShop.rar
http://www.cnblogs.com/Files/kellynic/NicPetShop.rar
含两个项目说明
为了方便程序更新,本版本为 .net remoting 版本
请确保您的 sql server 2005 能被外网访问得到,不支持生成本地的数据库。
小提示:如果您是局域网,但又想生成,可以试试安装“花生壳”。
今天在将 NicPetShop 的 DAL 添加存储过程控制后,测试到 SqlParameter 与 ExecuteReader 的问题。
当 SqlParameter.Direction 设置成 ParameterDirection.Output,将 SqlParameter 添加到 SqlCommand.Parameters 中,最后执行 SqlCommand.ExecuteReader 后无法得到返回的 @a 值 10,将 ExecuteReader 改成 ExecuteNoneQuery 后没有这个问题,为什么呢?
以前少用存储过程开发,一直都是用 sql,个人感觉 sql 比 sp 灵活得多。
在网上找了找相关资料,ExecuteReader 的链接没有关闭前无法得到需要返回的参数值,测试了一下后果真如此。
存储过程:
create proc dbo.test
(
@a int output
)
as

set @a = 10

测试代码:
SqlParameter parm = new SqlParameter("@a", System.Data.SqlDbType.Int);
parm.Direction = System.Data.ParameterDirection.Output;

SqlCommand cmd = new SqlCommand(ConnectionManager.GetConnection());
cmd.Parameters.Add(parm);
cmd.Connection.Open();

using (IDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
Response.Write(parm.Value + ","); //为空
cmd.Connection.Close();
Response.Write(parm.Value + ","); //10
}
我的程序所有地方都是用 dr.Dispose 来关闭 Connection 的。但 dr.Dispose 虽然可以关闭 Connection,但同时它也将自己毁消了,最后还是得不到 Parm.Value。
暂时找不到更好的方法,只有先把之前的改一改。
27/3 2:02 am 发表:
最好发现是 SqlHelper.cs 里的
cmd.Parameters.Clear(); 造成

public static IDataReader ExecuteReader(SqlConnection conn, CommandType cmdType, string cmdText, params SqlParameter[] cmdParms)
{
SqlCommand cmd = new SqlCommand();
PrepareCommand(cmd, conn, cmdType, cmdText, cmdParms);
SqlDataReader dr = null;

Exception ex = Lib.Trys(delegate()
{
if (cmd.Connection.State != ConnectionState.Open) cmd.Connection.Open();

try
{
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

} catch
{
if (!Lib.IsWeb) Thread.CurrentThread.Join(1000);
throw;
}
}, Lib.IsWeb ? 1 : 60);
LoggerException(cmd, ex);
return dr;
}


static void LoggerException(SqlCommand cmd, Exception e)
{

if (e == null)
{
cmd.Parameters.Clear(); //小小的错误啊
return;
}
string log = "〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓" + cmd.CommandText + "\r\n";

foreach (SqlParameter parm in cmd.Parameters)
{
log += Lib.PadRight(parm.ParameterName, 20) + " = " + Lib.PadRight(parm.Value == null ? "NULL" : parm.Value, 20) + "\r\n";
}
Log.Fatal(log + "\r\n\r\n", e);
cmd.Parameters.Clear();
cmd.Connection.Close();
throw e;
}