如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测

如何使用T-SQL备份还原数据库及c#如何调用执行?

准备材料:Microsoft SQL Server一部、需要还原的bak文件一只

一、备份

数据库备份语句:user master backup database 数据库名 to disk='保存路径\dbName.bak'

实战操作:这里要使用sql语句对TEST数据库进行备份,当然你也可以使用mssql自带工具进行操作,咦,麻烦死了

一句sql:

use master backup database  TEST to disk='C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\TEST.bak'

截图童叟无欺:


二、还原 相对较为麻烦,因为有日志文件的问题还有杀死连接的问题。

数据库还原语句:

use master restore database 数据库名 from disk='保存路径\dbName.bak'  WITH MOVE 'dbName_Data' to '保存路径\test20160428.mdf',

move 'dbName_Log' to '保存路径\test20160428_Log.mdf'

实战操作:这里我重新找了一个bak文件进行还原。源Bak文件名:FTZMIS20151218.bak

①首先,首先要查找到源bak文件中的数据文件和日志文件名称,需要一条SQL语句

sql:

 restore  filelistonly from disk = 'F:\华美数据核对20160407\FTZMIS20151218.bak'---查找BAK文件相关信息

 

结果:LogicalName列下的值就分别问数据文件名称和日志文件名称,待会要用到。

 ②正题开始,进行还原操作。

sql:

restore database kaifang from disk = 'F:\华美数据核对20160407\FTZMIS20151218.bak'--源bak文件 
with REPLACE--这句的意思是是否覆盖目标数据,也就是这里的数据库:kaifang
, move 'ABOQDB' to 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\FTZMIS.mdf'--数据文件还原后存放的新位置
,move 'ABOQDB_log' to 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\FTZMIS_1.ldf'--日志文件还原后存放的新位置

截图:暂无,还原还在执行

截图来了,

 

 

C#中索引器的作用和实现。

 

官方描述:索引器允许类或结构的实例就像数组一样进行索引。索引器形态类似于,不同之处在于它们的取值函数采用参数。

这一功能在创建集合类的场合特别有用,而在其他某些情况下,比如处理大型文件或者抽象有些资源等,能让类具有类似数组行为也是非常有用的。

大致结构

<modifier><return type> this [argument list]

{

get{//读}

set{//写}

}

其中:

modifier:修饰符,如:public,private,protected

this:是C#中一个特殊的关键字,表示引用类的当前实例。这里是当前类的索引。

argument list:这里是索引器的参数

一个简单例子,通过索引器返回一个字符串:

复制代码
class Sample { 
public string this [int index] { 
get {return "当前索引号为:" + index; } 
} 
} 

Sample s=new Sample();
Console.WriteLine(s[23]);

//结果
//当前索引号为:23
复制代码

技巧:

1.在定义索引器的时候,不一定只采用一个参数,同一类中还可以拥有一个以上的索引器,也就是重载。
2.索引器的参数可以采用任何类型,不过int是最为合理的类型。

属性和索引器差别

 1.类的每一个属性都必须拥有唯一的名称,而类里定义的每一个索引器都必须拥有唯一的签名(signature)或者参数列表(这样就可以实现索引器重载)。 

 2.属性可以是static(静态的)而索引器则必须是实例成员。 

 3.为索引器定义的访问函数可以访问传递给索引器的参数,而属性访问函数则没有参数。 

接口(interface):

类似数组的行为常受到程序实现者的喜爱,所以你还可以为接口定义索引器,IList和 IDictionary集合接口都声明了索引器以便访问其存储的项目。  在为接口声明索引器的时候,记住声明只是表示索引器的存在。你只需要提供恰当的访问函数即可,不必包括范围修饰符。以下代码把索引器声明为接口IImplementMe的一部分:

interface IImplementMe {  string this[int index]  {  get;  set;  } 

相应实现的类则必须为IimplementMe的索引器具体定义get和set访问函数。 

官方代码实例:

复制代码
class SampleCollection<T>
{
    // Declare an array to store the data elements.
    private T[] arr = new T[100];

    // Define the indexer, which will allow client code
    // to use [] notation on the class instance itself.
    // (See line 2 of code in Main below.)        
    public T this[int i]
    {
        get
        {
            // This indexer is very simple, and just returns or sets
            // the corresponding element from the internal array.
            return arr[i];
        }
        set
        {
            arr[i] = value;
        }
    }
}

// This class shows how client code uses the indexer.
class Program
{
    static void Main(string[] args)
    {
        // Declare an instance of the SampleCollection type.
        SampleCollection<string> stringCollection = new SampleCollection<string>();

        // Use [] notation on the type.
        stringCollection[0] = "Hello, World";
        System.Console.WriteLine(stringCollection[0]);
    }
}
// Output:
// Hello, World.
复制代码

码友实例:
非常实用

复制代码
namespace Study
{
    class Program
    {
        static void Main(string[] args)
        {
            ScoreIndex s = new ScoreIndex();
            s["张三", 1] = 90;
            s["张三", 2] = 100;
            s["张三", 3] = 80;
            s["李四", 1] = 60;
            s["李四", 2] = 70;
            s["李四", 3] = 50;
            Console.WriteLine("张三课程编号为1的成绩为:" + s["张三",1]);
            Console.WriteLine("张三的所有成绩为:");
            ArrayList temp;
            temp = s["张三"];
            foreach (IndexClass b in temp) 
            {
                Console.WriteLine("姓名:" + b.Name + "课程编号:" + b.CourseID + "分数:" + b.Score);
            }
            Console.ReadKey();
        }
    }
    class IndexClass 
    {
        private string _name;
        private int _courseid;
        private int _score;
        public IndexClass(string _name, int _courseid, int _score) 
        {
            this._name = _name;
            this._courseid = _courseid;
            this._score = _score;
        }
        public string Name 
        {
            get { return _name; }
            set { this._name = value; }
        }
        public int CourseID 
        {
            get { return _courseid; }
            set { this._courseid = value; }
        }
        public int Score 
        {
            get { return _score; }
            set { this._score = value; }
        }
    }
    class ScoreIndex 
    {
        private ArrayList arr;
        public ScoreIndex() 
        {
            arr = new ArrayList();
        }
        public int this[string _name, int _courseid] 
        {
            get 
            {
                foreach (IndexClass a in arr) 
                {
                    if (a.Name == _name && a.CourseID == _courseid) 
                    {
                        return a.Score;
                    }
                }
                return -1;
            }
            set 
            {
                arr.Add(new IndexClass(_name, _courseid, value)); //arr["张三",1]=90
            }
        }
        //重载索引器
        public ArrayList this[string _name] 
        {
            get 
            {
                ArrayList temp = new ArrayList();
                foreach (IndexClass b in arr) 
                {
                    if (b.Name == _name) 
                    {
                        temp.Add(b);
                    }
                }
                return temp;
            }
        }
    }
}
复制代码

 

 

jquery控制元素的隐藏和显示的几种方法。

组织略显凌乱,请耐心看!

 

使用jquery控制div的显示与隐藏,一句话就能搞定,例如:

1.$("#id").show()表示为display:block,

   $("#id").hide()表示为display:none;

2.$("#id").toggle()切换元素的可见状态。如果元素是可见的,切换为隐藏的;如果元素是隐藏的,则切换为可见的。

3.$("#id").css('display','none');//隐藏

   $("#id").css('display','block');//显示

   或者

   $("#id")[0].style.display='none';

  display=none 控制对象的隐藏搜索
  display=block控制对象的显示

4.$("#id").css('visibility','hidden');//元素隐藏

   $("#id").css('visibility','visible');//元素显示

CSS visibility 属性规定元素是否可见。
visible 元素可见。 
hidden 元素不可见。 
collapse 在表格元素中使用时,此值可删除一行或一列,但它不影响表格的布局。被行或列占据的空间会留给其他内容使用。如果此值被用在其他的元素上,会呈现为 "hidden"。 
inherit 从父元素继承 visibility 属性的值。

注意:

display:none和visible:hidden都能把网页上某个元素隐藏起来,在视觉效果上没有区别,但是在一些DOM操作中两者有区别:

display:none ---不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失,通俗来说就是看不见也摸不到。

visible:hidden--- 使对象在网页上不可见,但该对象在网页上所占的空间没有改变,即它仍然具有高度、宽度等属性,通俗来说就是看不见但摸得到。

复制代码
//第1种方法 ,给元素设置style属性  
$("#hidediv").css("display", "block");  
//第2种方法 ,给元素换class,来实现隐藏div,前提是换的class样式定义好了隐藏属性  
$("#hidediv").attr("class", "blockclass");  
//第3种方法,通过jquery的css方法,设置div隐藏  
$("#blockdiv").css("display", "none");  
  
$("#hidediv").show();//显示div    
$("#blockdiv").hide();//隐藏div 
复制代码

 

 

  • localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。

  • 他们均只能存储字符串类型的对象(虽然规范中可以存储其他原生类型的对象,但是目前为止没有浏览器对其进行实现)。

  • localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。

    sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。

  • 不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。

  • 同源的判断规则:

    http://www.test.com

    https://www.test.com (不同源,因为协议不同)

    http://my.test.com(不同源,因为主机名不同)

    http://www.test.com:8080(不同源,因为端口不同)

  • localStorage和sessionStorage使用时使用相同的API:

    localStorage.setItem("key","value");//以“key”为名称存储一个值“value”

    localStorage.getItem("key");//获取名称为“key”的值

    枚举localStorage的方法:

    for(var i=0;i<localStorage.length;i++){

         var name = localStorage.key(i)​;

         var value = localStorage.getItem(name);​

    }

    删除localStorage中存储信息的方法:

    localStorage.removeItem("key");//删除名称为“key”的信息。

    localStorage.clear();​//清空localStorage中所有信息

  •  通过getItem或直接使用localStorage["key"]获取到的信息均为实际存储的副本。

    例如:

    localStorage.key = {value1:"value1"}​;

    localStorage.key.value1='a'​;

    这里是无法​对实际存储的值产生作用的,下面的写法也不可以:

    ​localStorage.getItem("key").value1="a";

 

 

当创建AspNetCore项目时

      当我们创建一个AspNetCore项目时,需要我们手动添加Log:

services.AddLoging();

      我们发现,Log在微软原生的包Microsoft.Extensions.Logging、Microsoft.Extensions.Logging.Configuration内。并且创建ASPNetCore项目时,NetCore SDK已经包括了这两个Log的原生包。

 

使用类库

      目前本人在微软原生日志类库的基础之上,写了一个Log的扩展。目的是为了更好地扩展Log。当我们需要自定义自己的Log记录方式时,使用此库是你的明智选择。

类库地址信息

Nuget地址:https://www.nuget.org/packages/Alun.AspNetCore.Log.Extensions

GitHub开源地址:https://github.com/cjt321/Alun.AspNetCore.Log.Extensions

怎么使用此类库?

      首先,引用Nuget包的地址。在项目启动时,添加Log的配置。

复制代码
services.AddLogging(cfg =>

{

cfg.AddNvLog(new LogConfiguration(){UseTraceLog = false, UseDebugLog = true, UseInformationLog = true, UseErrorLog = true, UseCriticalLog = true})

.AddDefaultWriteLog();

});
复制代码

      在AddNvLog方法中,Log级别可配置:UseTraceLog、UseDebugLog、UseInformationLog、UseErrorLog、UseCriticalLog。 如果为true,则执行相应的Log。

那么什么时候记录Log呢?

      很简单,就像我们平时在NetCore中记录Log一样即可,无任何修改。可在源码WebApplicationDemo中看到记录Log。

clipboard

扩展类库

      当我们需要扩展日志以自己的逻辑记录到文件、队列、MySql、Mongodb等持久化时,可以扩展类库,扩展也很简单。

      对于mongodb扩展类库,nuget上也有个包,但是此包只能满足一般的需求,对于复杂的需求还不能满足,需要用户自己扩展自己的逻辑。

以Alun.AspNetCore.Log.Extensions.MongoDb为例

      此包是对Log保存在Mongodb中。

      此包在Nuget:https://www.nuget.org/packages/Alun.AspNetCore.Log.Extensions.MongoDb

      1)安装Alun.AspNetCore.Log.Extensions的nuget,因为这里需要用到mongodb,所以安装MongoDB.Driver。

      2)添加mongodb的writelog类,来继承IWriteLog。

clipboard[1]

      注意,我们在WriteLog方法中写日志,记录到mongodb中,此方法实现的是我们需要自定义的逻辑。这里把日志通过实体方法,持久化。

      为何要继承IWriteLog?因为我们需要用到自己的逻辑,继承此类为了使用DI/IOC时,可以直接注入继承IWriteLog的类。

      众所周知,使用DI/IOC时。有一好处,所有的对象都存放在容器上,如果需要修改容器里面对象,则可以通过注入的方式修改。对于继承,我们可以注入接口与实现类的方式,灵活变更实现类。

 

      所以,我们需要在容器上初始化IWriteLog与MongoDbWriteLog的关系。

      3)添加扩展配置

clipboard[2]

      我们主要看初始化mongodb的writelog配置,这里在容器中注入了IWriteLog, MongoDbWriteLog的继承关系。

如何使用?

      很简单,可查看WebApplicationDemo.MongoDb中,加入Mongdb的配置即可:

clipboard[3]

扩展类库的原理

      使用依赖注入,注入我们需要的Log逻辑类,如Mongdb中的MongoDbWriteLog。所以,需要扩展,只需要继承IWriteLog,并且注入,就能扩展类了,很方便。

 

总结

      读了本编文章的上部分时,慢慢会发现,使用Log扩展,就行完积木游戏一样,你想怎么‘组合’、怎么‘拆’都可以。如果你想把Log保存在队列,即实现IWriteLog,并且注入到容器中即可。如果你想把Log保存在Mongodb,一样的逻辑。所以,任意地组合,很方便。

      以上,都是Net Core正在发展的方向:低耦合、高内聚。在Log中提现了。并且默认自带了依赖注入,依赖注入的好处有很多,可查看本人的依赖注入文章系列。

 

 

span<T>之高性能字符串操作实测

 

   .net中的字符串操作性能问题由来已久,幸运的是微软推出了span<T>高性能指针操作封装工具类。这个类到底有多高的性能呢?网上传言反正很高,但是实际上在网上很难找到合适的测试实例,这让本人实在无力吐槽。经不住高性能这三个字的诱惑,本人还是了解了一番后做了几个简单样例来测试一番,下面列出几种字符串常见操作的测试代码及其运行结果。

一、String.Index 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.IndexOf(subStr);
6                 }
7             });
8 
9             Console.WriteLine($"string.IndexOf {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 for (int i = 0; i < count; i++)
 8                 {
 9                     strSpan.IndexOf(subStrSpan);
10                 }
11             });
12 
13             Console.WriteLine($"Span<T>.IndexOf {count} 次用时:{t2} 毫秒");
复制代码

 

二、String.Substring 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.Substring(0, str.IndexOf(subStr));
6                 }
7             });
8 
9             Console.WriteLine($"String.Substring {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 var index = strSpan.IndexOf(subStrSpan);
 8 
 9                 for (int i = 0; i < count; i++)
10                 {
11                     strSpan.Slice(0, strSpan.IndexOf(subStrSpan));
12                 }
13             });
复制代码

三、String.Split 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     var arr = str.Split(new string[] { splitStr }, StringSplitOptions.None);
6                 }
7             });
8 
9             Console.WriteLine($"String.Split {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var splitSapn = splitStr.AsSpan();
 6 
 7                 int m = 0, n = 0;
 8 
 9                 for (int i = 0; i < count; i++)
10                 {
11                     List<string> arr = new List<string>();
12 
13                     while (true)
14                     {
15                         m = n;
16                         n = strSpan.IndexOf(splitSapn);
17                         if (n > -1)
18                         {
19                             arr.Add(strSpan.Slice(0, n).ToString());
20                             strSpan = strSpan.Slice(n + splitSapn.Length);
21                         }
22                         else
23                         {
24                             break;
25                         }
26                     }
27 
28                 }
29             });
30 
31             Console.WriteLine($"Span<T>.Split {count} 次用时:{t2} 毫秒");
复制代码

四、String.Replace 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.Replace(splitStr, replaceStr);
6                 }
7             });
8 
9             Console.WriteLine($"String.Replace {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var splitSapn = splitStr.AsSpan();
 6 
 7                 int m = 0, n = 0;
 8 
 9                 for (int i = 0; i < count; i++)
10                 {
11                     List<string> arr = new List<string>();
12 
13                     while (true)
14                     {
15                         m = n;
16                         n = strSpan.IndexOf(splitSapn);
17                         if (n > -1)
18                         {
19                             arr.Add(strSpan.Slice(0, n).ToString());
20                             strSpan = strSpan.Slice(n + splitSapn.Length);
21                         }
22                         else
23                         {
24                             break;
25                         }
26                     }
27                     string.Join(replaceStr, arr);
28                 }
29             });
30 
31             Console.WriteLine($"Span<T>.Replace {count} 次用时:{t2} 毫秒");
复制代码

 

  怎么样,经过上面的测试,是不是觉的Span<T>确实是名不虚传?的确,在上面几个常见场景中,Span<T>的高性能确实不同凡响,差不多是10倍的性能优势!看到这里,小伙伴们是不是觉的字符串操作全改成Span<T>就行了?那下面的两个测试会让大家看清现实,在String.Contains中表现还不如原生的。

一、String.Contains 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     str.Contains(subStr);
6                 }
7             });
8 
9             Console.WriteLine($"string.Contains {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 for (int i = 0; i < count; i++)
 8                 {
 9                     strSpan.Contains(subStrSpan, StringComparison.CurrentCulture);
10                 }
11             });
12 
13             Console.WriteLine($"Span<T>.Contains {count} 次用时:{t2} 毫秒");
复制代码

  仔细一看,不对啊,Span<T>的Contains里面有其它的大小写和语言相关的判断啊。好,那再换一个原生方法对比测试一下。

二、String.Compare 测试

复制代码
1             var t1 = StopWacherHelper.DoTimer(() =>
2             {
3                 for (int i = 0; i < count; i++)
4                 {
5                     string.Compare(str, subStr, true);
6                 }
7             });
8 
9             Console.WriteLine($"string.Compare {count} 次用时:{t1} 毫秒");
复制代码
复制代码
 1             var t2 = StopWacherHelper.DoTimer(() =>
 2             {
 3                 var strSpan = str.AsSpan();
 4 
 5                 var subStrSpan = subStr.AsSpan();
 6 
 7                 for (int i = 0; i < count; i++)
 8                 {
 9                     strSpan.Contains(subStrSpan, StringComparison.CurrentCultureIgnoreCase);
10                 }
11             });
12 
13             Console.WriteLine($"Span<T>.Contains {count} 次用时:{t2} 毫秒");
复制代码

  还是被反杀了,这说明Span<T>的这个Contains方法可能真的只能在某些地方才能用,不然性能反而会有所下降。

       如果对上述感兴趣,可以点击这里下载测试源码,更多请点击左下角的推荐,谢谢~

posted @ 2018-11-20 17:09  ~雨落忧伤~  阅读(150)  评论(0编辑  收藏  举报