心雨纷扬的博客

一个简单的博客

  • 如何删除工作项

    1. 使用Tfs管理员账户登录

    2. 使用Cmd打开命令行窗口

    • 如果是32位系统

      cd "C:\\Program Files\\Microsoft Visual Studio 10.0\\Common7\\IDE"

    • 64位系统

      cd "C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE"

    1. 使用 witadmin.exe destroywi命令,按下面的方式
      ``witadmin.exe destroywi /Collection:http:\\[ServerName]:8080\tfs\[CollectionName] /id:[WI ID]`

    可以一次删除多个工作项,使用逗号分隔工作项Id,比如10,22,30。可以使用 /noprompt屏蔽提示消息

    1. 假设服务器名称为ServerDemo,团队项目集合名称为TeamDemo,要删除Id为17、18的工作项,则使用如下命令:

    witadmin.exe destroywi /Collection:http:\\\ServerDemo:8080\\tfs\\TeamDemo /id:17,18

    1. 上述方法为微软工作人员答疑,经测试,在Tfs2010 简体中文正式版,能够正常的删除工作项。请注意,在做这个操作之前,先关闭Vs2010。
  • 使用Ghost或者Windows 镜像备份的情形下,如何备份项目集?

    当我们安装了操作系统、开发环境之后,我们常常为此时干净的系统,做一个镜像备份,有时候是使用Ghost,有时候是使用Windows 7或者Sql Server 2008 R2的Server Backup功能做镜像备份。当然,因为安装了Sql server 2008 R2和Tfs2010、Vs2010之后,C:盘往往有17G左右,因为速度的关系我们推荐使用Ghost,能在20分钟之内恢复C:\盘,使用Windows Server Backup功能,常常需要数个小时。

    我们一般做两个Ghost镜像,第一个是操作系统安装好、驱动安装好、操作系统各项更新完成、常用软件如Live Writer、QQ、网银、迅雷、Winrar之类安装好、操作系统配置好(比如关机不要输入关机原因、登录不需要按Ctrl+Alt+Del、或者自动使用某个账户登录而无需输入密码等等),这些完成之后做一个镜像,叫做工作镜像。在这个镜像做好之后,安装开发环境,然后做第二个镜像:开发环境镜像。请注意做镜像前关闭休眠功能并删除休眠文件、禁用虚拟内存或将虚拟内存文件放在D:盘,这样会大大的减少镜像文件的大小。

    那么,每次恢复镜像,会造成Tfs的项目管理信息丢失。所以,这之前需要备份Tfs的数据库,这是件很麻烦的事情,下面列出我目前采用的一个取巧的方法,请注意我在自己个人的开发机器上安装的是Tfs的Basic版本:

    1. 安装Sql 2008 R2和Tfs 2010之后,默认的项目集保存在C:盘,此时我们在C盘将三个Tfs数据库,备份在C:盘默认的Sql Server备份位置。这是为了防止Tfs系统完全不匹配,造成不能正常工作的最后挽救方法。
    2. 在Sql server中设置默认的数据库位置在D:\Database或D:盘的其他目录
    3. 重新启动系统,注意,不要忽略这一步,我们在上一步的设置或许仅仅是修改了一个配置项,目前Sql的默认数据库文件存放路径,还是在C:盘,没有改变。
    4. 使用Tfs 2010的管理控制台,创建新的团队项目集合,假设我们为其命名为TeamWork。
    5. 此时,你会发现在D:\Database下,有了一个新的数据库Tfs_TeamWork
    6. 将Sql server的三个Tfs_开头的数据库,同样备份到C:盘,这个时候再开始为系统做Ghost镜像,今后每次使用Ghost恢复干净的开发环境,就不用考虑Tfs数据库的问题,直接用Ghost恢复就行了。当然,前提是你不要删除掉D:\Database目录下的相关数据库。以后,只需要随时备份Tfs_TeamWork以策万全。
    7. 如果D:\盘的数据库出现意外,最坏的情况,我们使用C:盘的初始备份能让系统正常运行起来,然后再用平常做的Tfs_TeamWork的备份,按照标准的恢复模式进行。 注意,如果我们仅备份某个团队项目集合的数据库,而没有备份Tfs_Configuration数据库,则在上次创建镜像到此次恢复镜像期间创建的团队项目会丢失。
  • 安装好Scrum模版后,创建新的团队项目集合时,如何使用? 选择该团队项目集合,右键,运行过程模版管理器。选上载,找到安装目录:默认是C:\Program Files (x86)\Microsoft\Microsoft Visual Studio Scrum 1.0\Process Template 此后创建团队项目时,就多了Scrum项目这一项。

  • 如何清除Vs2010的工作区影射关系的缓存信息? 在原有的团队项目集合移除,或者更换Tfs服务器后,一些工作区的影射关系仍然存在,这会导致“将解决方案添加到源代码管理”之类的功能不可使用。 这些信息缓存于文件C:\Users\Administrator\AppData\Local\Microsoft\TeamFoundation\3.0\Cache\VersionControl.config中,只要把跟旧服务器相关的 ServerInfo 节点删掉,问题即可解决。

  • 如何还原已经备份的团队项目集合数据库?

    1. 关闭Tfs服务: 运行: “C:\Program Files\Microsoft Team Foundation Server 2010”\Tools\TFSServiceControl quiesce
    2. 还原数据库,请注意两个选项:选择从设备恢复、选择覆盖原数据库
    3. 启动Tfs服务: 运行: “C:\Program Files\Microsoft Team Foundation Server 2010”\Tools\TFSServiceControl unquiesce
  • 删除团队项目

    "C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7\\IDE\\TFSDeleteProject" /force /collection:http://x200:8080/Stock Faster

    其中http://x200:8080是服务器名称和端口,Stock是团队项目集合的名称,Faster是Stock团队项目集合中要删除的项目

有时候我们手头上的数据库可能只剩下了mdf文件,而日志文件丢失了或者损坏了, 那么你可以尝试使用以下方法重建事务日志,注意sql 2K不是这个语句

1
2
3
USE master; GOCREATE DATABASE nuke ON 
(FILENAME = 'H:\\Mdf-BackUp\\Nuke.mdf'), --数据库文件所在
(FILENAME = 'H:\\Mdf-BackUp\\Nuke\_Log.ldf')---指定重建的日志文件路径 FOR ATTACH\_REBUILD_LOGGO

大家以前应该碰到过这样的情况: 在作业或者项目数据库中,创建和映射了数据库帐号aspuser,当你重装了数据库,或者备份了到另外的服务器上去还原的时候,你的aspuser帐号不能对数据库正常访问了,即使在数据库的登录帐号中创建了相同的aspuser帐号,也不行。 今天在嘉为培训的时候,主将老师谈到这个问题,提供了很好的方案:

–报告孤立用户 Exec sp_change_users_login ‘Report’

执行这个存储过程可以查出数据库中,存在相同问题的帐号的列表

–修复用户与已经存在的登录账号间的映射 Exec sp_change_users_login ‘Auto_Fix’,’aspuser’ –通过更新用户,共修复了 1 个孤立用户。这个就是修复帐号的存储过程(前提是数据库登录帐号中有aspuser)

–创建登录并修复用户与登录账号间的映射 Exec sp_change_users_login ‘Auto_Fix’,’aspuser’,null,’000000’

创建aspuser帐号的同时,对帐号进行修复,一举两得

如果系统中存在端口冲突就有可能发生本情况. IIS默认使用80端口进行HTTP通信. 如果除IIS外的应用程序正在运行并且正在相同的IP地址上使用80端口,在您试图使用IIS管理器启动网站时您也可能收到该错误讯息. 解决办法

  1. 直接修改网站的端口,不再绑定80,而切换其他端口,如果这样就不会有问题了,但是如果访问网站的时候就得加上端口号,很麻烦
  2. 使用工具查看谁在占用TCP80端口:一般占用该端口的是网站服务器,比如我装了两个Web服务器,IIS 5.1和Apache+php+Mysql,如果你先启用了默认配置的Apache(你的IIS网站没有启动)那么,你的TCP80端口就会被占用,导致IIS启动时发生0x8ffe2740错误。停止了PHP服务器你的IIS又可以启动了。当然,不光光是网站会占用这个端口的,今天早上我就发现了一个奇怪的事情,我没有启动我的PHP服务器,但是还是发生了这个错误,很奇怪啊,我使用了360安全卫士的常用–>高级工具–>网络连接查看器,看到skype个破东西居然占着我宝贵的80端口,是可忍孰不可忍,马上把它退出了,然后启动我的IIS,OK,成功启动。唉,一无是处的Skype尽给我找麻烦,为了防止下次还被skype占用,可以在skype设置里的高级里的连接选项里,去掉将80端口与443端口作为备用端口的选项。我使用的skype是5.0国际

前台 <script> var a = ''; a = '<%# PrintStr()%>'; alert(a); </script> 值得注意的是这个调用的方法不能是private或者internal的. 如果PrintStr()该方法是有返回值的时候需要在page_load里加入Page.DataBind()方法,不然不会成功返回值的 方法需要传参数的话,不知道咋搞了

表ChooseAuthorize和membership的User表,联合查询

1
2
3
4
5
6
7
8
9
10
11
12
/// <summary> 
/// 取得当前登陆用户收藏授权记录的用户集合
/// </summary>
/// <returns></returns>
public static DataTable GetAuthorizeUserList() {
string uid = new ChooseAuthorizeInfo().GetCurrentUserId();
Aggregate AuthorizerId = new Aggregate(ChooseAuthorize.AuthorizerIdColumn, "AuthorizerId", AggregateFunction.GroupBy);
Aggregate RealName = new Aggregate(UserInfo.RealNameColumn, "RealName", AggregateFunction.GroupBy);
Aggregate ReceiverId = new Aggregate(ChooseAuthorize.ReceiverIdColumn, "ReceiverId", AggregateFunction.GroupBy);
DataTable dt = new Select(ChooseAuthorize.Columns.ReceiverId, UserInfo.Columns.RealName).From<ChooseAuthorize>().InnerJoin(UserInfo.UserIdColumn, ChooseAuthorize.ReceiverIdColumn).Where(ChooseAuthorize.Columns.AuthorizerId).IsEqualTo(uid).ExecuteDataSet().Tables[0];
return dt;
}

环境:有一张Global_CollectInfo_tb来存放有关收藏的记录包括收藏者ID,收藏的记录的主表ID,收藏的记录在具体副表里的ID,收藏记录在主表里的ID,具体的数据记录放在各个副表里. Global_TableDetail_tb里存放有关表的具体信息,包括列名,列类型,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
USE \[cys\] GO 
/****** 对象:  StoredProcedure \[dbo\].\[getMyCollectList\_sp\]    脚本日期: 07/15/2010 08:46:24 ******/
SET ANSI\_NULLS ON GO SET QUOTED\_IDENTIFIER ON GO -- =============================================
-- Author:  dzd -- Create date: 2010-7-14 -- Description: 收藏库多表查询 -- =============================================
ALTER PROCEDURE \[dbo\].\[getMyCollectList\_sp\]
-- Add the parameters for the stored procedure here
@UserId nvarchar(50) AS --定义sql语句变量
declare @nsql nvarchar(2000) DECLARE @strOrder varchar(400); -- 排序类型 DECLARE @StrGetFields varchar(1000);
-- 需要返回的列
--定义临时表
create  TABLE #t(\[id\] nvarchar(50),\[字段1\] nvarchar(500),\[字段2\] nvarchar(500),\[字段3\] nvarchar(500),\[字段4\] nvarchar(500),\[字段5\] nvarchar(500),\[来源表\] nvarchar(500))
--定义游标
DECLARE tnames\_cursor CURSOR FOR SELECT     Global\_TableDetail\_tb.TableName,Global\_TableDetail\_tb.TableDetailId FROM         Global\_TableDetail\_tb INNER JOIN  Global\_CollectInfo\_tb ON Global\_TableDetail\_tb.TableDetailId = Global\_CollectInfo\_tb.CollectTableId WHERE     (Global\_CollectInfo\_tb.CollectorId = @UserId) and Global\_TableDetail\_tb.IsShow='true' group by Global\_TableDetail\_tb.TableName,Global\_TableDetail\_tb.TableDetailId
--打开游标
OPEN tnames\_cursor declare @TableName nvarchar(100),@TableDetailId nvarchar(100) FETCH next from tnames\_cursor into @TableName,@TableDetailId while @@fetch\_status=0 begin select top 5 @StrGetFields=isnull(@StrGetFields+',','')+case when ColumnType ='date' then 'convert(nvarchar(100), ' else '' end + ColumnName+ case when ColumnType ='date' then ',120)' else '' end from Global\_ColumnConfiger\_tb where [TableId=@TableDetailId](TableId=@TableDetailId) order by ColumnIndex asc SET @nsql = 'SELECT id,' [+@StrGetFields](mailto:+@StrGetFields) +',TableName FROM  Global\_TableDetail\_tb INNER JOIN Global\_CollectInfo\_tb ON Global\_TableDetail\_tb.TableDetailId = Global\_CollectInfo\_tb.CollectTableId INNER JOIN ' + @TableName + '_副表 ON Global\_CollectInfo\_tb.CollectRecordId = '+ @TableName+'_副表.id WHERE (Global\_CollectInfo\_tb.CollectorId = ['''+@UserId+''']('''+@UserId+''')) AND (Global\_TableDetail\_tb.IsShow = ''true'')'

print(@nsql) insert into #t
execute(@nsql) set @StrGetFields = null FETCH next from  tnames\_cursor into @TableName,@TableDetailId end CLOSE tnames\_cursor DEALLOCATE tnames_cursor select * from #t

我在开发过程中发现有需要根据数据库传来的表的不同,产生不同的gridview的列,但是,其中根据数据表生成的列是要放到几个模板列之间的.前台代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="divGv" style="margin: 0 auto; text-align: center;" runat="server"> 
<asp:GridView ID="gvList" runat="server" AutoGenerateColumns="False" OnRowCommand="gvList\_RowCommand" OnRowCreated="gvList\_RowCreated" OnRowDataBound="gvList\_RowDataBound" DataKeyNames="id">
<Columns>
<asp:TemplateField>
<ItemTemplate>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="序号">
<ItemTemplate> </ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="管理">
<ItemTemplate></ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView> <webdiyer:AspNetPager ID="AspNetPager1" runat="server" ShowBoxThreshold="10" NumericButtonCount="8" OnPageChanging="AspNetPager1\_PageChanging" SubmitButtonClass="saveBtn"> </webdiyer:AspNetPager>
</div>

后台代码相当多,可能有人说为什么前台里的模板列里没有控件呢?这个是因为我现在要做的是插入列,使用的是insert,如果是使用了add,那么这个是可以直接在前台完全写好模板列的,也没有下面的这么麻烦了,贴出后台代码,希望有人可以给出更简单的办法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//创建及设置字段 
public void setfields() {
int recordCount = 0; string tabname = getTabName();
//取得一次分页数据,以用来确定列
string where="where 1=1";
DataTable dt = ColumnConfigerInfo.GetValueByTableName(AspNetPager1.PageSize,AspNetPager1.CurrentPageIndex,tabname,where,out recordCount);
//设置总记录数
AspNetPager1.RecordCount = recordCount;
int num = dt.Columns.Count;
//循环插入列,并绑定字段
for (int i = 3; i < num; i++) {
BoundField cc = new BoundField();
cc.DataField = dt.Columns[i].ColumnName;
cc.HeaderText = dt.Columns[i].ColumnName;
cc.ItemStyle.Wrap = false; //
if(dt.Columns[i\].ColumnName.Equals("外键"))
{
    //隐藏掉该列
   cc.Visible = false;
}
//判断是否是时间类型的列
if (dt.Columns[i].DataType.Name == "DateTime") {
//设置时间格式
cc.DataFormatString = "{0:yyyy-MM-dd}"; cc.HtmlEncode = false; } cc.ReadOnly = true; gvList.Columns.Insert(i-1, cc);
}
//绑定分页控件,数据源,
Gridview,aspnetpager UI.BindCtrl(recordCount, dt.DefaultView, gvList, AspNetPager1); }
/// <summary>
/// 取得表名
/// </summary>
/// <returns></returns>
private string getTabName() {
int tabid = int.Parse(lbltabId.Text);
TableDetailInfo tab = new TableDetailInfo(tabid);
string tabname = tab.TableName;
return tabname;
}
     看到这里,是不是觉得很简单呢?错了.麻烦的在后面呢.这个使用了列的insert方法后,进行翻页的时候模板列如果本来在前台写了控件的就会消失,这个还不知道原因,网上找了找,据说是微软的bug.所以我追加下面的代码来解决这个问题 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
         //行创建时候添加模板列的控件 
protected void gvList_RowCreated(object sender, GridViewRowEventArgs e) {
if (e.Row.RowType == DataControlRowType.Header) {
int cc = gvList.Columns.Count;
CheckBox cb = new CheckBox();
cb.ID = "ckbAll";
e.Row.Cells[0].Controls.Add(cb);
cb.AutoPostBack = true;
cb.CheckedChanged += new EventHandler(cb_CheckedChanged); }
if (e.Row.RowType == DataControlRowType.DataRow) {
int cc=gvList.Columns.Count;
CheckBox ckb = new CheckBox();
ckb.ID = "ckbDetail";
e.Row.Cells[0].Controls.Add(ckb);
LinkButton lbtn1 = new LinkButton();
lbtn1.Text = " [收藏] ";
lbtn1.CommandName = "collect";
e.Row.Cells[cc - 1].Controls.Add(lbtn1);
lbtn1.CommandArgument = e.Row.RowIndex.ToString();
LinkButton lbtn2 = new LinkButton();
lbtn2.CommandName = "attention";
e.Row.Cells[cc - 1].Controls.Add(lbtn2); lbtn2.Text = " [中标] "; lbtn2.CommandArgument = e.Row.RowIndex.ToString();
LinkButton lbtn3 = new LinkButton();
lbtn3.CommandName = "compare";
e.Row.Cells[cc - 1].Controls.Add(lbtn3);
lbtn3.Text = " [比对] ";
lbtn3.CommandArgument = e.Row.RowIndex.ToString();
LinkButton lbtn4 = new LinkButton();
lbtn4.CommandName = "detail";
e.Row.Cells[cc - 1].Controls.Add(lbtn4);
lbtn4.Text = " [查看详细] ";
lbtn4.CommandArgument = e.Row.RowIndex.ToString(); } }

其中类似lbtn4.CommandArgument = e.Row.RowIndex.ToString();的代码是绑定行值,以方便后面进行操作 而

1
2
3
4
5
6
7
8
if (e.Row.RowType == DataControlRowType.Header) {
int cc = gvList.Columns.Count;
CheckBox cb = new CheckBox();
cb.ID = "ckbAll";
e.Row.Cells[0].Controls.Add(cb);
cb.AutoPostBack = true;
cb.CheckedChanged += new EventHandler(cb_CheckedChanged);
}

则是为了生成全选按钮,并订阅CheckedChanged事件.以用来激发下面的事件,来全选上所有复选框

1
2
3
4
5
6
7
8
9
10
protected void cb_CheckedChanged(object sender, EventArgs e) { 
for (int i = 0; i < gvList.Rows.Count; i++) {
CheckBox ckb = (CheckBox)gvList.Rows[i].Cells[0].Controls[0] as CheckBox; CheckBox ckbAll = sender as CheckBox;
if (ckbAll.Checked) {
ckb.Checked = true;
} else {
ckb.Checked = false;
}
}
}