[转载]Android系统数据共享---Content Provider学习小结

mikel阅读(826)

[转载]Android系统数据共享—Content Provider学习小结 – 宁 静 致 远 – 博客园.

Content Provider作为Android应用程序中的四大组件之一,主要是为了实现在各应用程序之间数据共享,增强应用程序的复用,例如,在开发过程中,需要获取手机中的通讯录信息,这时完全不需要自己重新开发读取数据的整个过程,

而是直接访问系统自带的Content Provider对象来直接获取数据(此例子只是说明有现成的能满足需要的ContentProvider即可随时“拿来”,只要有相应权限, 不用管它是来自哪个应用程序里)。

在Content Provider使用过程中,还需要借用ContentResolver对象作为代理,间接操作ContentProvider来获取数据。 ContentProvider可以看作是对应着一个或多个数据表(类似查询后返回的数据集)。另外重要的概念还有Uri,通过它来找到相应的 ContentProvider、并能定位到对应的数据表或字段。

相关的知识经过整理,特列出下面这张思维导图,以方便自己经常温故,也希望能给大家带来一丝思维上的提示,也算是抛砖引玉了,呵呵

Content Provider知识

夜已经深了,明天又要上班了,面对新的一周,整理思绪,继续前行……

[转载]蛙蛙推荐:用.net 4.0构建新浪微博开发平台应用

mikel阅读(880)

[转载]蛙蛙推荐:用.net 4.0构建新浪微博开发平台应用 – 蛙蛙池塘 – 博客园.

摘要:现在很多互联网应用都推出了开放平台,开心人人新浪淘宝豆瓣腾讯,还有飞信也即将推出开放平台,大多数开发平台都会用OAuth认证,并提供返回json数据的Rest接口,用.NET 4.0的新特性来开发这些平台的应用有着天然的优势,一起来看看。

认证

要想使用开发平台的数据和接口,第一步肯定是登录和认证,OAuth被越来越多的开放平台所认可和使用,TerryLee已经介绍过在.NET里如何实现OAuth认证,不过是针对豆瓣平台的一些示例代码,新浪微博的OAuth认证有一些不同的地方,一会儿我会标识出来。sarlmolapple为新浪提供了新浪微博开放平台的c#版本SDK,但没有完全对新浪微博的所有接口进行支持。因此我借鉴了两位的代码写了个针对新浪微博的精简版的OAuth认证,因为简单,如果大家想开发其它开放平台的应用,也可以很快比猫画虎做出来。

首先还是要下载别人写好的OAuthBase.cs文 件,然后继承该类写一些自定义的逻辑,后来发现只通过子类来实现自定义逻辑还不好使,所以迫不得已还是修改了OAuthBase.cs类,因为新浪微博开 放平台要求生成OAuth签名时,多了一个Verifier参数,所以在生成basestring时(GenerateSignatureBase方法) 要加上这个参数。

//NOTE:add by onlytiancai@gmail.com 兼容sina登录,参考了http://code.google.com/p/opensinaapi/
if (!string.IsNullOrEmpty(Verifier) && httpMethod == "GET")
{
parameters.Add(new QueryParameter(oAauthVerifier, Verifier));
}

准备一下OAuth认证的配置项,这些配置项大家可以在数据库里配置或者写个自定义配置节在Web.config里配置,为了简单,我就先写死了,如下:

public class OAuthConfig
{
public static OAuthConfig Instance = new OAuthConfig();
public OAuthConfig()
{
RequestTokenUri = "http://api.t.sina.com.cn/oauth/request_token";
AuthorizeUri = "http://api.t.sina.com.cn/oauth/authorize";
AccessTokenUri = "http://api.t.sina.com.cn/oauth/access_token";
ApiKey = "xxxx"; //在新浪微博开放平台申请
ApiKeySecret = "xxxxxxxxxxxxxxxxxx";//在新浪微博开放平台申请
}
public string RequestTokenUri { get; set; }

public string ApiKey { get; set; }

public string ApiKeySecret { get; set; }

public string AuthorizeUri { get; set; }

public string AccessTokenUri { get; set; }
}

请求open api接口时一般要拼写PostData格式的数据,而PostData的格式是类似”?p1=a&p2=b&p3=c”,这种格式,要手动拼写这样格式的字符串很麻烦,所以我们想要一种优雅的方式,比如:

get_request(new {p1="a", p2="b", p3="c"})

这个参数是一个C# 3.5的匿名类,然后在get_request方法里可以通过反射获取到属性名和值,构建成PostData格式,但这样做性能会稍差一些,我们可以用另外一种相近的格式,如下:

get_request(new Pairs { { "p1", "a" }, {"p2", "b"}, "p3", "c" } )

这里的参数是一个Pairs类,后面的大括号套着大括号是.net 3.5的集合初始化语法,这个Pairs是我在(Using C# 3.0 Anonymous Types as Dictionaries )这篇博客的评论里看到的,我略微修改了一下,如下:

public class Pairs : List>
{
public void Add(String key, String value)
{
Add(new KeyValuePair(key, value));
}

public string ToPostData(Func valueHandler = null)
{
StringBuilder sb = new StringBuilder();
foreach (var pair in this)
{
if (sb.Length > 0)
sb.Append("&");
sb.AppendFormat("{0}={1}", pair.Key, valueHandler == null
? pair.Value : valueHandler(pair.Value));
}
return sb.ToString();
}
}

我只增加了一个ToPostData的方法,其中有一个可选的参数用来在拼接PostData时对参数值进行处理,可选参宿是.net 4.0提供的机制,如果不提供这个参数,我就按原文拼写参数值

我继承OAuthBase写了一个OAuthHelper类,其中OAuthRequest方法用来发送一个OAuth请求,如下:

public string OAuthRequest(string uri, Pairs data = null, string method = "GET")
{
//1、准备获取签名所需参数
string nonce = GenerateNonce();
string timeStamp = GenerateTimeStamp();
if (data == null)
data = new Pairs();
data.Add("source", OAuthConfig.Instance.ApiKey); //添加默认的source参数
uri += uri.IndexOf("?") > 0 ? "&" : "?";
uri += data.ToPostData(str => UrlEncode(str)); //防止参数里有",%,="等字符

//2、获取签名
string normalizeUrl, normalizedRequestParameters;
string sig = GenerateSignature(
new Uri(uri),
OAuthConfig.Instance.ApiKey,
OAuthConfig.Instance.ApiKeySecret,
Token,
TokenSecret,
method,
timeStamp,
nonce,
OAuthBase.SignatureTypes.HMACSHA1,
out normalizeUrl,
out normalizedRequestParameters);
normalizedRequestParameters = normalizedRequestParameters + "&"
+ OAuthSignatureKey + "=" + HttpUtility.UrlEncode(sig);

//3、发送WEB请求并接受数据
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
method == "POST" ? normalizeUrl : normalizeUrl + "?" + normalizedRequestParameters);
request.Method = method;
if (method == "POST")
{
using (StreamWriter sw = new StreamWriter(request.GetRequestStream()))
{
sw.Write(normalizedRequestParameters);
}
}

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(request.GetResponse()
.GetResponseStream(), System.Text.Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}

具体步骤我都做了注释,其中 GenerateNonce,GenerateTimeStamp,UrlEncode,GenerateSignature都是父类提供的方法,直接调 用即可,根据名字也很容易想出它的功能,如果你做的不是新浪微博开放平台的应用,这里可能要相应的做一些小改动。

然后是进行OAuth的三步认证,第一步获取RequestToken,第二步让用户进行授权,一般情况下会提示用户登录新浪微博或者提示用户授权或拒绝授权你的应用访问用户的新浪微博数据,第三步就是拿到AccessToken去访问受限的资源,具体过程大家可以看这里。有了上面我们写的方法,这三步就很简单了。

///
/// 登录第一步:获取RequestToken
///
public void GetRequestToken()
{
string response = OAuthRequest(OAuthConfig.Instance.RequestTokenUri);
if (response.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs[OAuthTokenKey] != null)
{
this.Token = qs[OAuthTokenKey];
this.TokenSecret = qs[OAuthTokenSecretKey];
}
}
}

///
/// 登录第二部:Response.Redirect到这个页面,提示用户授权
///
///
用户认证成功后返回的地址 ///
public string GetAuthorizeUri(string callbackUri)
{
return string.Format("{0}?oauth_token={1}&&oauth_callback={2}",
OAuthConfig.Instance.AuthorizeUri,
this.Token, callbackUri);
}

///
/// 登录第三部:获取AccessToken,成功登录
///
public void GetAccessToken()
{
string response = OAuthRequest(OAuthConfig.Instance.AccessTokenUri);
if (response.Length > 0)
{
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs[OAuthTokenKey] != null)
{
this.Token = qs[OAuthTokenKey];
this.TokenSecret = qs[OAuthTokenSecretKey];
}
}
}

其中Token和TokenSecret是OAuthHelper的两个string类型成员。

获取JSON数据

一般开放平台的接口可以返回xml格式或JSON格式的数据,如果解析XML数据会很不通用,每一个接口需要写一个方法,而返回json的 话.NET 4.0提供的JavaScriptSerializer可以对json数据进行序列化和反序列化,json格式的数据可以反序列化成 Dictionary<string, object>类型或其类型的数组,其中object又是一个Dictionary<string, object>,但我们对Dictionary的操作会很麻烦,我们想办法吧它转换成一个C# 4.0的dynamic类型,这里有篇帖子(Turning JSON into a ExpandoObject )介绍了如何去做,我在此基础上改动了一下,并提供了一个直接把open api返回的数据转换成ExpandoObject的方法,如下。

///
/// 发送OAuth请求,并把返回的json结果转换成dynamic类型
///
///
请求地址,请确保返回json数据 ///
请求数据 ///
HttpMethod ///
public ExpandoObject OAuthRequestDynamic(string uri, Pairs data = null, string method = "GET")
{
string result = OAuthRequest(uri, data, method);
if (result == null)
return null;
return Expando(result);
}

public static ExpandoObject Expando(string json)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
object obj = serializer.DeserializeObject(json);
if (obj is ICollection)
return Expando(new Dictionary() { { "arr", obj } });
else
return Expando((Dictionary)obj);
}

//http://coderjournal.com/2010/07/turning-json-into-a-expandoobject/
private static ExpandoObject Expando(IDictionary dictionary)
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary)expando;

foreach (var item in dictionary)
{
bool alreadyProcessed = false;

if (item.Value is IDictionary)
{
expandoDic.Add(item.Key, Expando((IDictionary)item.Value));
alreadyProcessed = true;
}
else if (item.Value is ICollection)
{
var itemList = new List<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100" height="100" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><embed type="application/x-shockwave-flash" width="100" height="100"> </embed></object>

if (itemList.Count &gt; 0)
{
expandoDic.Add(item.Key, itemList);
alreadyProcessed = true;
}
}
if (!alreadyProcessed)
expandoDic.Add(item);
}

return expando;
}

这下可好了,访问opan api,直接返回的就是带类型的了,省了解析的工序了,和Python差不多,直接写出成员就行。

开发第一个应用

去新浪微博开放平台注册一个账户,得到app key和app key secret,然后就可以开发测试应用了,新建一个Default.aspx页,摆放如下控件。

<div><img src="&lt;%# Eval(" alt="" />" alt="" /&gt;
<strong>&lt;%# Eval("user.name") %&gt;:</strong>&lt;%# Eval("text")%&gt;(&lt;%# Eval("created_at")%&gt;)

</div>

控件的功能根据名字可以推测出来,先看登录

protected void btnLogin_Click(object sender, EventArgs e)
{
OAuthHelper oauth = new OAuthHelper();
oauth.GetRequestToken();
Session["oauth_token"] = oauth.Token;
Session["oauth_token_secret"] = oauth.TokenSecret;
string url = oauth.GetAuthorizeUri("http://localhost:1812/");
Response.Redirect(url);
}

先获取RequestToken,然后获取用户认证页地址,重定向过去,提示用户登录,用户登录完了之后会返回到calback uri,这里填写是本页,新浪会在返回的页面上提供oauth_verifier参数,如果有这个参数就说明是用户登录成功返回的,所以我们要在 Page_Load里做一些处理,困了,就不写那么多说明了,大家看看,大多都是借鉴了sarlmolapple的示例代码。

protected void Page_Load(object sender, EventArgs e)
{
Session[Guid.NewGuid().ToString()] = 1; //生成cookie里的sessionid,防止Redirect回来丢失Session
if (!Page.IsPostBack)
{
OAuthHelper oauth = new OAuthHelper();
if (Request["oauth_verifier"] != null)
{
oauth.Token = Session["oauth_token"].ToString();
oauth.TokenSecret = Session["oauth_token_secret"].ToString();
oauth.Verifier = Request["oauth_verifier"];
oauth.GetAccessToken();
Session["oauth_token"] = oauth.Token; ;
Session["oauth_token_secret"] = oauth.TokenSecret;

Response.Redirect("/Default.aspx");
}
if (Session["oauth_token"] != null)
{
this.lblMessage.Text = "登录成功";
this.btnLogin.Visible = false;
this.btnTimeline.Visible = true;
}
else
{
this.lblMessage.Text = "未登录";
this.btnLogin.Visible = true;
this.btnTimeline.Visible = false;
}
}
}

登录成功后,我们获取public_timeline,并直接绑定在Repeater上,不做任何解析,你猜能不能用。

protected void btnTimeline_Click(object sender, EventArgs e)
{
OAuthHelper oauth = new OAuthHelper();
oauth.Token = Session["oauth_token"].ToString();
oauth.TokenSecret = Session["oauth_token_secret"].ToString();
dynamic json = oauth.OAuthRequestDynamic(
"http://api.t.sina.com.cn/statuses/public_timeline.json",
new Pairs { { "count", "5" } });
rpt1.DataSource = json.arr;
rpt1.DataBind();
}

猜对了,不能用,但是加上如下代码就能用了

protected new object Eval(string expression)
{
string[] arr = expression.Split('.');
object obj = this.Page.GetDataItem();
IDictionary items = obj as IDictionary;
if (items != null)
{
if (arr.Length == 1)
return items[arr[0]];
else if (arr.Length == 2)
return ((IDictionary)items[arr[0]])[arr[1]];
else
throw new NotSupportedException("哥,表达式too长了,不支持呀。");
}
else return DataBinder.Eval(this.Page.GetDataItem(), expression);
}

以上代码是在网上找到的一段,出处忘了,我在它的基础上修改了一下,支持了json的二级数据的绑定,可以直接在Eval里写“user.name”这样的表达式。

public_timeline返回的json样子大概是如下:

[
{
"created_at" : "Tue Nov 30 14:34:35 +0800 2010",
"text" : "吃力不讨好的事情我是坚决不会再做了,RI你个仙人!发飙~~~~我只想说档次和素质在那里去了,
你也就只能在这种地方混!",
"truncated" : false,
"in_reply_to_status_id" : "",
"annotations" :
[

],
"in_reply_to_screen_name" : "",
"geo" : null,
"user" :
{
"name" : "习惯寂寞吗",
"domain" : "",
"geo_enabled" : true,
"followers_count" : 5,
"statuses_count" : 61,
"favourites_count" : 0,
"city" : "1",
"description" : "",
"verified" : false,
"id" : 1676792942,
"gender" : "f",
"friends_count" : 26,
"screen_name" : "习惯寂寞吗",
"allow_all_act_msg" : false,
"following" : false,
"url" : "http://1",
"profile_image_url" : "http://tp3.sinaimg.cn/1676792942/50/1284648784",
"created_at" : "Wed Dec 30 00:00:00 +0800 2009",
"province" : "51",
"location" : "四川 成都"
},
"favorited" : false,
"in_reply_to_user_id" : "",
"id" : 3978753419,
"source" : "<a rel="\&quot;nofollow\&quot;" href="\">新浪微博</a>"
},
...
]

最后来张图吧

[原创]修改SQLServer2008的内置账户方法

mikel阅读(1274)

刚装的SQLServer2008选择的内置账户是Network Services ,可是在附加数据库的时候,提示无权限访问文件,去google了一下发现时内置账户的问题,于是更改了内置账户为Local Services 结果 SQL Server服务没办法启动了!

于是去控制面板->管理工具->服务中将SQL Server的账户改为内置账户,重启服务,附加数据库成功!

[转载]Asp.NET MVC Widget开发 - Html.Widget扩展方法

mikel阅读(972)

[转载]Asp.NET MVC Widget开发 – Html.Widget扩展方法 – Creative dream – 博客园.

ASP.NET开发博客类系统,我们经常都会用到Widget,像在线好友、最近访问好友、最新留言等,关于ASP.NET MVC与Asp.NET视图的差异,这里不再说了,大家可去查一下,接下来我以“我的好友”列表来要介绍在Asp.NET MVC实现这一功能以及结构设计。

  • 开发工具:VS 2010 EN
  • 开发语言:Visual C#
  • ASP.NET MVC 3
  1. ASP.NET MVC Widget – 设计
  2. ASP.NET MVC Widget – Controller控制器
  3. Asp.NET MVC Widget – ViewEngine
  4. Asp.NET MVC Widget – Mobile支持
  5. Asp.NET MVC Widget – Html.Widget扩展方法

前4篇文章中,已实现Widget具体开发,并支持当前流行的手机客户端,以及如何在页面中使用:

@{Html.RenderAction(“Friends”, “Widget”); }

每次这样总感觉有些烦琐,而我们想要的只是指定Widget名称就行了:

@Html.Widget(“Friends”)

实现方法是很简单,扩展HtmlHelper方法

具体代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Web.Mvc.Html
{
public static class WidgetExtensions
{
public static MvcHtmlString Widget(this HtmlHelper htmlHelper, string widget)
{
htmlHelper.RenderAction(widget, "Widget");
return MvcHtmlString.Empty;
}
}
}

部署和安装SQL Server 2008数据库(二)

mikel阅读(1026)

SQL Server 2008SQL Server 2005安装过程有许多不同,比如网络环境的问题、账户的问题、安装向导的问题等等。目前很多公司的服务器从Windows Server 2003也逐渐升级升级到了2008,数据库升级到SQL Server 2008 也在所难免,所以平时有很多朋友在问部署SQL Server 2008过程中的问题,笔者在这里进行详细总结。
SQL Server 2008 安装的环境如下:
1, 工作组环境下的服务器
2, 域环境下的域控制器
3, 域环境下的成员服务器
4, 群集环境
事实上从开发和应用的角度讲,很多devoloper很少接触基于域控制器的开发应用,所以他们的应用多半都跑在工作环境下的服务器上,IIS中会发布很多网站,服务器本身会承载数据库的角色等,此时会涉及到在工作组环境下安装SQL Server 2008。但微软平台企业级应用开发很少有域不参与的地方,比如微软的CRMSharePointuc等产品的二次开发、.NET平台为了适应企业环境和组织架构在域模式下的应用开发等,此时会涉及到在域控制器、成员服务器和群集中安装SQL Server 2008
无论是哪一种环境下安装SQL Server 2008,都会碰到为每个SQL Server 2008服务配置账户的问题。安装SQL Server 2008时会用的账户如下:
1, 本地用户帐户
2, 域用户帐户
3, 内置系统帐户
l Network Service 帐户(网络服务)
l Local Service 帐户(本地服务)
l Local System 帐户(本地系统)
本地用户帐户
工作组环境,如果计算机不在域中,则建议使用不具有 Windows 管理员权限的本地用户帐户。
域用户帐户
如果服务必须与网络服务进行交互,则访问类似于文件共享的域资源;如果服务使用到运行 SQL Server 的其他计算机的链接服务器连接,则可以使用具有最低特权的域帐户。许多服务器到服务器的活动只能使用域用户帐户来执行。此帐户应由域管理员在域环境内预先创建。
Local Service 帐户:
Local Service 帐户是一个内置帐户,与 Users 组的成员具有相同级别的资源和对象访问权限。如果有个别服务或进程的安全性受到威胁,则此有限访问权限有助于保护系统的安全性。以 Local Service 帐户身份运行的服务将以一个没有凭据的 Null 会话形式访问网络资源。请注意,SQL Server SQL Server 代理服务不支持 Local Service 帐户。该帐户的实际名称为“NT AUTHORITY\LOCAL SERVICE”
Network Service 帐户:
Network Service 帐户是一个内置帐户,比 Users 组的成员拥有更多的对资源和对象的访问权限。以 Network Service 帐户身份运行的服务将使用计算机帐户的凭据访问网络资源。该帐户的实际名称为“NT AUTHORITY\NETWORK SERVICE”
Local System 帐户:
Local System 是一个具有高特权的内置帐户。它对本地系统有许多权限并作为网络上的计算机。该帐户的实际名称为“NT AUTHORITY\SYSTEM”
如果是在工作组环境下安装SQL Server 2008:
使用的账户是本地用户帐户,内置账户(网络服务账户、本地系统账户等)。
在域环境上(涵盖成员服务器)安装 SQL Server 2008:
出于安全方面的考虑,Microsoft 建议不要将 SQL Server 2008 安装在域控制器上。 SQL Server 安装程序不会阻止在作为域控制器的计算机上进行安装,但存在以下限制:
Windows Server 2003 上,SQL Server 服务可在域帐户或本地系统帐户下运行。
在域控制器上,无法在本地服务帐户或网络服务帐户下运行 SQL Server 服务。此时用的账户一般是域账户和本地系统账户。
SQL Server 安装到计算机上之后,无法将此计算机从域成员更改为域控制器。 必须先卸载 SQL Server,然后才能将主机计算机更改为域控制器。
SQL Server 安装到计算机上之后,无法将此计算机从域控制器更改为域成员。 必须先卸载 SQL Server,然后才能将主机计算机更改为域成员。
在群集节点用作域控制器的情况下,不支持 SQL Server 故障转移群集实例。
SQL Server 安装程序不能在只读域控制器上创建安全组或设置 SQL Server 服务帐户。 在这种情况下,安装将失败。
SQL Server 2008 安装程序安装该产品所需的以下软件组件:
l .NET Framework 3.5 SP1
l SQL Server Native Client
l SQL Server 安装程序支持文件
l SQL Server 安装程序要求使用 Microsoft Windows Installer 4.5 或更高版本
如果安装SQL Server 2008之前已经装了Visual Studio 2008,安装时出现错误,请先安装Visual Studio 2008 SP1
SQL Server 2008安装SSRS服务时,不再像SQL Server 2005必须要先安装IIS,安装SQL Server 2008不在需要IIS的支持。
下面我们以域环境下的域控制器为例安装SQL Server 2008
步骤1:启动安装程序后,如下图:

步骤2:在SQL Server 2008装中心的计划里面,可以用系统配置检查器检测服务器是否具备条件安装SQL Server 2008系统配置检查器在安装过程中会被安装程序多次调用。还可以通过在早期SQL Server版本的服务器上安装安装升级顾问来自动帮助你分析升级需要的成本和能升级什么服务,安装完安装升级顾问后,可以连接到早期版本的实例进行分析。这里单击系统配置检查器来检测系统。

系统配置检查器检测的情况如下图:

步骤3:单击安装后,在这里我们可以选择全新安装SQL Server 2008,安装群集,升级安装等。这里单击全新SQL Server独立安装或向现有安装添加功能,如下图:

步骤4:可以使用180天的企业评估版等,也可以输入你购买的产品密钥进行授权安装。

输入产品密钥:

如果你输入的是企业版的密钥就会看到企业版的许可条款,如果输入的是开发版的密钥就会看到开发版的许可条款:

步骤5:安装程序支持文件,如下图:

步骤6:安装程序支持规则,如下图:

步骤7:功能选择,根据需要选择想要安装的功能,如下图:

步骤8:可以配置成默认实例或者命名实例,如果默认实例还没被以前安装的实例占用,则可以使用默认实例。如下图:

可以修改命名实例的实例ID

我们这里使用默认实例进行安装:

步骤9:磁盘空间要求,如下图:

步骤10:配置各个服务使用的账户,如下图:

步骤11:配置排序规则,默认即可,如下图:

步骤12:选中“混合模式”,指定sa账户的密码,并指定SQL Server管理员,通过单击“添加当前用户”选择当前账户即可,也可以选择其他的账户。如下图:

步骤13:配置数据库引擎的数据目录的路径,根据需求修改,可以把各个目录的路径配置到不同的磁盘,减小I/O的负载。这里采用默认。如下图:

步骤14:可以启用FilesStream特性,这里默认没有启用,如下图:

步骤15:为Analysis Services服务指定管理员,这里选择当前用户,如下图:

步骤16:配置Analysis Services服务的数据目录,这里采用默认配置,如下图:

步骤17Reporting Serivices配置,默认即可,如下图:

步骤18:错误和使用报告,如下图
步骤19:检测安装规则,看是否能顺利安装,如下图:
步骤20:准备安装,如下图:
步骤21:安装进度,慢慢等吧 ,^_^。如下图:
步骤22:各个功能都安装完成,如下图:
步骤23:安装完成,如下图:
本节结束。

本文出自 “李涛的技术专栏” 博客,请务必保留此出处http://terryli.blog.51cto.com/704315/439573

[转载]使用 jQuery dataTables - 2 四种数据来源

mikel阅读(1029)

[转载]使用 jQuery dataTables – 2 四种数据来源 – haogj – 博客园.

四种数据来源

对于 dataTables 来说,支持四种表格数据来源。

最为基本的就是来源于网页,网页被浏览器解析为 DOM 对象,在 dataTables 中称为  DOM 来源。


$(document).ready(function() {
	$('#example').dataTable();
} );

第二种数据来源为数组, JavaScript 中的数组,通过在初始化对象中传递一个名为 aaData 的数组,同样可以提供表格数据,前缀 aa 说明这是一个数组的数组,外层的数组表示表格的行,每一行同样是一个数组。


$(document).ready(function() {
	$('#demo').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="example"></table>' );
	$('#example').dataTable( {
		"aaData": [
			/* Reduced data set */
			[ "Trident", "Internet Explorer 4.0", "Win 95+", 4, "X" ],
			[ "Trident", "Internet Explorer 5.0", "Win 95+", 5, "C" ],
			[ "Trident", "Internet Explorer 5.5", "Win 95+", 5.5, "A" ],
			[ "Trident", "Internet Explorer 6.0", "Win 98+", 6, "A" ],
			[ "Trident", "Internet Explorer 7.0", "Win XP SP2+", 7, "A" ],
			[ "Gecko", "Firefox 1.5", "Win 98+ / OSX.2+", 1.8, "A" ],
			[ "Gecko", "Firefox 2", "Win 98+ / OSX.2+", 1.8, "A" ],
			[ "Gecko", "Firefox 3", "Win 2k+ / OSX.3+", 1.9, "A" ],
			[ "Webkit", "Safari 1.2", "OSX.3", 125.5, "A" ],
			[ "Webkit", "Safari 1.3", "OSX.3", 312.8, "A" ],
			[ "Webkit", "Safari 2.0", "OSX.4+", 419.3, "A" ],
			[ "Webkit", "Safari 3.0", "OSX.4+", 522.1, "A" ]
		],
		"aoColumns": [
			{ "sTitle": "Engine" },
			{ "sTitle": "Browser" },
			{ "sTitle": "Platform" },
			{ "sTitle": "Version", "sClass": "center" },
			{
				"sTitle": "Grade",
				"sClass": "center",
				"fnRender": function(obj) {
					var sReturn = obj.aData[ obj.iDataColumn ];
					if ( sReturn == "A" ) {
						sReturn = "<b>A</b>";
					}
					return sReturn;
				}
			}
		]
	} );
} );

aoColumns 参数用来定义表格的列,这是一个数组,其中的每一个对象用来定义一列。

对于每一个列对象:

sTitle 定义列的标题

sClass 定义列的样式

fnRender 函数用来渲染列,这个函数将会传递一个参数对象,这个参数对象的 iDataColumn 属性表示当前的列索引,aData 表示当前的行数组。函数返回的结果将被填充到单元格中。

当然了,对于表示行的数组来说,长度应该是相同的。如果某一行数据缺失或者提供了过多地数据的话,就会得到一个警告。

错误的数组

第三种数据来源是 AJAX,也就是说可以向服务器发一个请求来获得数据。

在初始化参数对象中,通过 sAjaxSource 的属性传递请求的地址,bProcessing 表示是否需要显示一个工作中的提示。

在 JSON 方式返回的数据中,需要一个名为 aaData 的属性来提供实际的数据。

$(document).ready(function() {
	$('#example').dataTable( {
		"bProcessing": true,
		"sAjaxSource": '../examples_support/json_source.txt'
	} );
} );

其中 json_source.txt 就是 JSON 数据,其中定义了一个名为 aaData 的属性。这个文件可以在下载的压缩包中找到,在 examples\examples_support 文件夹中。

最后一种数据来源是服务器,对于大量的数据来说,你可能希望在服务器端完成所有的操作,分页、排序、过滤等等。dataTable 可以通过服务器完成这些功能,甚至其他的服务器,像  Google Gears 或者 Adobe Air,这样的话,dataTables 就是一个显示数据和提供操作事件的前端模块。

$(document).ready(function() {
	$('#example').dataTable( {
		"bProcessing": true,
		"bServerSide": true,
		"sAjaxSource": "../examples_support/server_processing.php"
	} );
} );

对于服务器来说,可以通过请求参数来获得当前的操作信息。

类型 名称 说明
int iDisplayStart 显示的起始索引
int iDisplayLength 显示的行数
int iColumns 显示的列数
string sSearch 全局搜索字段
boolean bEscapeRegex 全局搜索是否正则
boolean bSortable_(int) 表示一列是否在客户端被标志位可排序
boolean bSearchable_(int) 表示一列是否在客户端被标志位可搜索
string sSearch_(int) 个别列的搜索
boolean bEscapeRegex_(int) 个别列是否使用正则搜索
int iSortingCols 排序的列数
int iSortCol_(int) 被排序的列
string sSortDir_(int) 排序的方向 “desc” 或者 “asc”.
string sEcho DataTables 用来生成的信息

这篇文章介绍了在 C# 中结合 LINQ 使用 DataTables 进行服务端处理的经验 jQuery DataTables Plugin Meets C#

服务器应该返回如下的 JSON 格式数据

类型 名称 说明
int iTotalRecords 实际的行数
int iTotalDisplayRecords 过滤之后,实际的行数。
string sEcho 来自客户端 sEcho 的没有变化的复制品,
string sColumns 可选,以逗号分隔的列名,
array array mixed aaData 数组的数组,表格中的实际数据。
<pre>{
    "sEcho": 3,
    "iTotalRecords": 57,
    "iTotalDisplayRecords": 57,
    "aaData": [
        [
            "Gecko",
            "Firefox 1.0",
            "Win 98+ / OSX.2+",
            "1.7",
            "A"
        ],
        [
            "Gecko",
            "Firefox 1.5",
            "Win 98+ / OSX.2+",
            "1.8",
            "A"
        ],
        ...
    ] 
}

[转载]使用 jQuery dataTables - 1

mikel阅读(1036)

[转载]使用 jQuery dataTables – 1 – haogj – 博客园.

JQuery 的插件 dataTables 是一个优秀的表格插件,提供了针对表格的排序、浏览器分页、服务器分页、筛选、格式化等功能。dataTables 的网站上也提供了大量的演示和详细的文档进行说明,为了方便学习使用,这里一步一步进行说明。

首先,需要到 dataTables 的网站 http://www.datatables.net/ 下载这个脚本库,

目前的版本是 1.7.5,下载的压缩包中使用的 JQuery 是 1.4.4 。现在 JQuery1.5.1 已经发布,所以,这里使用最新的 jQuery 1.5.1 。

然后,在网页中先加入 jQuery 的引用,然后,加入 dataTables 的引用。

配置脚本

对于 dataTables 来说,表格必须通过 thead 和 tbody 进行说明,如下所示,

<table id="example" class="display" border="0" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th> Rendering engine</th>
<th> Browser</th>
<th> Platform(s)</th>
<th> Engine version</th>
<th> CSS grade</th>
</tr>
</thead>
<tbody>
<tr class="odd gradeX">
<td>Trident</td>
<td>Internet Explorer 4.0</td>
<td>Win 95+</td>
<td class="center">4</td>
<td class="center">X</td>
</tr>

如果没有 thead 将会报错。

表格错误

最为简单的使用方式,就是零配置的方式。

/*
* Example init
*/
$(document).ready(function(){
$('#example').dataTable();
});

表格的效果

默认效果

注意,红框表示了四个默认的设置效果,分别用来选择每页的行数,表格的过滤器,表格的信息和换页。

此时,使用了几个默认的参数设置。在 dataTables 中,参数名称的前缀用来说明参数的数据类型,很明显,b 表示布尔类型,i 表示整数类型,s 表示字符串类型。

  • bPaginate: 是否分页,默认为 true,分页
  • iDisplayLength : 每页的行数,每页默认数量:10
  • sPaginationType: 分页样式,支持两种内置方式,two_button 和 full_numbers, 默认使用 two_button。
  • bLengthChange : 是否允许用户通过一个下拉列表来选择分页后每页的行数。行数为 10,25,50,100。这个设置需要 bPaginate 支持。默认为 true。
  • bFilter: 启用或禁止数据过滤,默认为 true。 注意,如果使用过滤功能,但是希望关闭默认的过滤输入框,应使用 sDom
  • bInfo: 允许或者禁止表信息的显示,默认为 true,显示信息。

我们也可以通过传递一个初始化参数对象来改变这些设置。例如,下面的例子将每页的行数设置为 20 行。

$(function () {
$("#example").dataTable(
{
iDisplayLength: 20
}
);
});

[原创]自定义VS2008的起始页的新闻订阅RSS

mikel阅读(1118)

自定义起始页的新闻区

  1. “工具”菜单上单击“选项”
  2. 展开“环境”,然后单击“启动”
  3. “起始页新闻频道”中,输入新闻 RSS 源 URL。
  4. 单击“确定”

同时可以使用VS2008的浏览器浏览网页,这样不用再VS2008和浏览器间来回切换了,的确方便了不少

[原创]树形分类数据库表结构设计

mikel阅读(1815)

最近项目中涉及到树形结构的分类信息管理功能,最终显示格式如下:

树形结构显示效果图

最初我设计的数据库表结构如下:

ID 分类名称 上级分类ID 当前分类层次

结果添加了几个不同的顶级分类的子类后,查询出数据显示的效果如下:

顺序混乱的树形显示

顺序混乱的树形显示

“鞋”这个分类数据库中上级分类Id存储的是服装分类的ID,但是我们查询出来后,遍历显示的效果确实在汽车用品里,因为我们是按默认ID排序的,所以显示的时候根本没有层级关系,尽管数据库中存储着“当前分类层次”这个字段值,还是需要我们手工处理显示问题,要么利用SQL语句根据层级关系一级一级的读取数据返回数据,要么用JavaScript在页面一级进行表格的row操作来切换行的位置,都是很费时费力的方法,于是想到记录每一个分类的路径信息,于是修改了数据库表结构如下:

ID 分类名称 上级分类ID 当前分类层次 分类路径

这个“分类路径”是做什么用的?

首先分类路径存储的是当前分类到顶级分类的完整路径,以一级ID,二级ID,…..,当前级ID的格式存储,这有什么好处呢?

大家利用SQL按分类路径进行一下排序就知道了,是不是自然的按照层级关系读取出数据来了,读取的数据如下:

数据库表结构

数据库表结构

好了,既然表结构出来了,那么就需要考虑path数据什么时候生成,当然是插入新分类的时候生成于是有了存储过程如下:

ALTER PROCEDURE Store_GoodsCategoryCreate
	@Identifier int,
	@ParentID int,
	@Sort_Order int,
	@is_Show int,
	@grade int,
	@Cate_Level int,
	@CategoryName nvarchar(20)=NULL,
	@Keywords nvarchar(500)=NULL,
	@Cate_Desc nvarchar(MAX)=NULL,
	@Cate_Unit nvarchar(20)=NULL,
	@home_display nvarchar(20)=NULL,
	@Filter_attr nvarchar(500)=NULL,
	@Cate_Path nvarchar(500)=NULL
AS
BEGIN TRAN
	--选择ParentNode的Level+1
	SELECT @Cate_Level=Cate_Level+1 FROM Store_GoodsCategory WHERE Identifier=@ParentID
	IF @Cate_Level=0
	BEGIN
		ROLLBACK TRAN
	END
	--插入分类数据
	INSERT INTO Store_GoodsCategory(ParentID,Sort_Order,is_Show,grade,Cate_Level,CategoryName,
       Keywords,Cate_Desc,Cate_Unit,home_display,Filter_attr,Cate_Path)
	VALUES(@ParentID,@Sort_Order,@is_Show,@grade,@Cate_Level,@CategoryName,@Keywords,@Cate_Desc,
         @Cate_Unit,@home_display,@Filter_attr,@Cate_Path)
	IF(@@ERROR&gt;0)
	BEGIN
		ROLLBACK TRAN
	END
	SET @Identifier=@@IDENTITY --记录刚刚添加的ID

	--更新本节点的路径信息
	UPDATE Store_GoodsCategory
	SET
		Cate_Path=(select Cate_Path+','+Cast(@Identifier as nvarchar(20)) from Store_GoodsCategory where Identifier=@ParentID )
	WHERE
		Identifier=@Identifier

	IF(@@ERROR&gt;0)
	BEGIN
		ROLLBACK TRAN
	END

COMMIT TRAN

[转载]WPF中实现对Flash的播放及(循环)截图

mikel阅读(1177)

[转载]WPF中实现对Flash的播放及(循环)截图 – SongShu – 博客园.

要想实现Flash的播放支持,需要借助Flash自身的ActiveX控件.

而WPF作为一种展现层的技术,不能自身插入COM组件,必需借助Windows Form引入ActiveX控件.
比较标准的实现方法,可以参考以下链接:http://blogs.msdn.com/b/jijia/archive/2007/06/07/wpf-flash-activex.aspx
而本文则是介绍通过借助System.Windows.Forms下的WebBrowser实现.
但无论是那一种方法,本质上都是通过在WPF程序中引用Windows Form窗体,再在其内引入ActiveX控件.
实现对Flash的播放
首先,引入可在WPF上承载 Windows 窗体控件的元素:WindowsFormsHost,及添加对 Windows 窗体的引用.
具体的实现过程:项目引用–添加引用–选择 “WindowsFormsIntegration” 及 “System.Windows.Forms” –添加
在WPF页面分别添加这两者的引用:
XAML中的所有实现代码:
<Window x:Class="Capture.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:host="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="File Capture" Height="600" Width="800"
Unloaded="Window_Unloaded"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<host:WindowsFormsHost x:Name="host">
<forms:WebBrowser x:Name="browser"></forms:WebBrowser>
</host:WindowsFormsHost>
<Grid Background="Gray" Grid.Column="1">
<UniformGrid Rows="5" VerticalAlignment="Top">
<Button x:Name="btnOpen" Width="100" Height="30" Click="btnOpen_Click" Margin="0,10">Open File</Button>
<Button x:Name="btnCapture" Width="100" Height="30" Click="btnCapture_Click" Margin="0,10">Start Capture</Button>
<Button x:Name="btnStop" Width="100" Height="30" Click="btnStop_Click" Margin="0,10">Stop Capture</Button>
<CheckBox x:Name="cboxLoop" IsChecked="True" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="25,10,0,10">Loop Capture</CheckBox>
</UniformGrid>
</Grid>
</Grid>
</Window>

当需要把一选中的Flash文件(.swf 文件)添加进WebBrowser 中播放:
browser.Navigate(currentPath);
实现对Flash的截图
实现对Flash的截图,只要使用WebBrowser的基类WebBrowserBase里面的DrawToBitmap方法.
参数Bitmap为所绘制的位图(需初始化位图的大小),Rectangle为截取WebBrowser内容的区域(大小)
private void Capture()
{
 string fileName = System.IO.Path.GetFileNameWithoutExtension(currentPath);
string capturePath = string.Format(&quot;{0}\\Capture\\{1}&quot;, System.Environment.CurrentDirectory, fileName);

 if (!Directory.Exists(capturePath))
 {
 Directory.CreateDirectory(capturePath);
}

 Bitmap myBitmap = new Bitmap((int)host.ActualWidth, (int)host.ActualHeight);
 System.Drawing.Rectangle DrawRect = new System.Drawing.Rectangle(0, 0, (int)host.ActualWidth, (int)host.ActualHeight);
 browser.DrawToBitmap(myBitmap, DrawRect);

 string timeNow = DateTime.Now.ToString(&quot;yyyyMMddHHmmssfff&quot;);

 myBitmap.Save(string.Format(&quot;{0}\\{1}_{2}.png&quot;, capturePath, fileName, timeNow));
}

界面效果:
如上图所示,本实例实现了对Flash的循环截图,时间间隔为1秒.本部分比较简单,
通过使用System.Windows.Threading下的DispatcherTimer即可实现.具体可参考本文最后的附件代码.
实例代码下载:
1 xmlns:host="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" 2 xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"