威尼斯人线上娱乐

入门教程,开发品种小技巧

4 4月 , 2019  

1.私下认可EF生成的连接字符串比较的长和奇怪,若想使用普通的连天字符串来连接EF,则足以经过创办分种类,同等看待写2个构造函数,在构造函数中经过动态拼接EntityConnectionString获得EF所需的连年字符串,具代完成代码如下:

1.暗中认可EF生成的总是字符串相比较的长和奇特,若想使用普通的接连字符串来连接EF,则足以经过创制分门类,因人而异写三个构造函数,在构造函数中通过动态拼接EntityConnectionString获得EF所需的连天字符串,具代达成代码如下:

新近付出品种中用到的编码小技巧汇总表明,开发项目小技巧

威尼斯人线上娱乐,壹.暗中同意EF生成的连年字符串相比的长和新奇,若想利用普通的总是字符串来连接EF,则能够透过创办分档次,不分轩轾写三个构造函数,在构造函数中经过动态拼接EntityConnectionString得到EF所需的再三再四字符串,具代完成代码如下:

    public partial class DataEntities
    {
        private static ConcurrentDictionary<string, string> entityConnStrings = new ConcurrentDictionary<string, string>();

        public DataEntities(string connName)
            : base(BuildEntityConnectionString(connName))
        {

        }

        private static string BuildEntityConnectionString(string connName)
        {

            if (!entityConnStrings.ContainsKey(connName))
            {
                var connStrSetting = System.Configuration.ConfigurationManager.ConnectionStrings[connName];

                EntityConnectionStringBuilder entityConnStrBuilder = new EntityConnectionStringBuilder();
                entityConnStrBuilder.Provider = connStrSetting.ProviderName;
                entityConnStrBuilder.ProviderConnectionString = EncryptUtility.DesDecrypt("XXXXX", connStrSetting.ConnectionString);
                entityConnStrBuilder.Metadata = "res://*/Data.csdl|res://*/Data.ssdl|res://*/Data.msl";
                string entityConnString = entityConnStrBuilder.ToString();
                entityConnStrings.AddOrUpdate(connName, entityConnString, (key, value) => entityConnString);
            }
            return entityConnStrings[connName];
        }
    }

只顾下边包车型地铁类是贰个分部类:partial,同时BuildEntityConnectionString方法是贰个静态方法,在BuildEntityConnectionString方法中ProviderConnectionString
= EncryptUtility.DesDecrypt(“XXXXX”,
connStrSetting.ConnectionString);是主要,小编那里是对config中的连接字符串
也都开始展览了加密,故此处小编急需解密,若无那个要求能够直接:ProviderConnectionString
=connStrSetting.ConnectionString即可。后续实例化EF上下文对象时,请使用:DataEntities(string
connName)那么些布局涵数即可,DataEntities是切实的EF上下文对象,大家的EF上下文类名均或者不均等。

二.支撑一个通用对象的XML连串化(即:多少个类中有可变类型属性成员,供给不相同的体系结果及变化分化的行列成分名称),具体贯彻代码如下:

二个内需被连串化成XML的类:在那之中供给转变的XML成分detail必需有子成分,且子成分名称及子成分内部属性依照项目标不及而各异(即:detail成分下的子成分是可变的)

    [XmlRootAttribute("master")]
    public class DemoMaster<T> where T : class
    {
        [XmlElement("attr")]
        public string DemoAttr { get; set; }

        [XmlElement("detail")]
        public DemoDetail<T> DemoDetail { get; set; } //关键点在这里,该属性元素为:detail,但其子元素根据T不同而不同

    }
    public class DemoDetail<T> : IXmlSerializable where T : class
    {
        public T body { get; set; }

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            string bodyStr = reader.ReadInnerXml();
            this.body = XmlHelper.XmlDeserialize<T>(bodyStr, Encoding.UTF8);
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteRaw(XmlHelper.XmlSerialize(this.body, Encoding.UTF8, true));
        }
    }

    [XmlTypeAttribute("list-a", AnonymousType = false)]
    public class DemoDetailA
    {
        public string Apro1 { get; set; }

        public string Apro2 { get; set; }

        public string Apro3 { get; set; }
    }

    [XmlTypeAttribute("list-b", AnonymousType = false)]
    public class DemoDetailB
    {
        public string Bpro1 { get; set; }

        public string Bpro2 { get; set; }

        public string Bpro3 { get; set; }
    }

    [XmlTypeAttribute("list-c", AnonymousType = false)]
    public class DemoDetailC
    {
        public string Cpro1 { get; set; }

        public string Cpro2 { get; set; }

        public string Cpro3 { get; set; }
    }

注意下面代码中,须要关爱:德姆oDetail属性及德姆oDetail<T>类,德姆oDetail属性仅是为着生成detail成分节点,而子节点则由德姆oDetail<T>类来拓展变更,德姆oDetail<T>是完结了IXmlSerializable接口,在XML连串化时,德姆oDetail<T>类仅将body属性对应的T类型实例内容实行系列化(WriteRaw),而反类别化时,则先反种类化body属性对应的T类型实例,然后赋值给body属性,那也是高强之处,德姆oDetail<T>类自己并未真正参加到种类化中,故类别化的字符串也看不到德姆oDetail<T>类相关的成分,德姆oDetail<T>类仅仅是3个XML种类化格式生成的中介。种类化的XML结果如下:

种类化代码:

            var demo1 = new DemoMaster<DemoDetailA>()
            {
                DemoAttr = "demo1",
                DemoDetail = new DemoDetail<DemoDetailA>() { body = new DemoDetailA() { Apro1 = "demoA1", Apro2 = "demoA2", Apro3 = "demoA3" } }
            };

            var demo2 = new DemoMaster<DemoDetailB>()
            {
                DemoAttr = "demo2",
                DemoDetail = new DemoDetail<DemoDetailB>() { body = new DemoDetailB() { Bpro1 = "demoB1", Bpro2 = "demoB2", Bpro3 = "demoB3" } }
            };

            var demo3 = new DemoMaster<DemoDetailC>()
            {
                DemoAttr = "demo3",
                DemoDetail = new DemoDetail<DemoDetailC>() { body = new DemoDetailC() { Cpro1 = "demoC1", Cpro2 = "demoC2", Cpro3 = "demoC3" } }
            };

            textBox1.Text = XmlHelper.XmlSerialize(demo1, Encoding.UTF8);

            textBox1.Text += "\r\n" + XmlHelper.XmlSerialize(demo2, Encoding.UTF8);

            textBox1.Text += "\r\n" + XmlHelper.XmlSerialize(demo3, Encoding.UTF8);

种类化的XML:

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo1</attr>
    <detail><list-a>
    <Apro1>demoA1</Apro1>
    <Apro2>demoA2</Apro2>
    <Apro3>demoA3</Apro3>
</list-a></detail>
</master>

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo2</attr>
    <detail><list-b>
    <Bpro1>demoB1</Bpro1>
    <Bpro2>demoB2</Bpro2>
    <Bpro3>demoB3</Bpro3>
</list-b></detail>
</master>

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo3</attr>
    <detail><list-c>
    <Cpro1>demoC1</Cpro1>
    <Cpro2>demoC2</Cpro2>
    <Cpro3>demoC3</Cpro3>
</list-c></detail>
</master>

三.winform DataGridView
实现内定列采用密码框格局显示与编写制定,以及列绑定到复合属性(即:绑定到多层次属性),具体达成代码如下:

            dataGridView1.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);
            dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);


        public string EvaluateValue(object obj, string property)
        {
            string retValue = string.Empty;
            string[] names = property.Split('.');

            for (int i = 0; i < names.Count(); i++)
            {
                try
                {
                    var prop = obj.GetType().GetProperty(names[i]);
                    var result = prop.GetValue(obj, null);
                    if (result != null)
                    {
                        obj = result;
                        retValue = result.ToString();
                    }
                    else
                    {
                        break;
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }

            return retValue;
        }


        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {

            if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName.Contains("."))
            {
                e.Value = EvaluateValue(dataGridView1.Rows[e.RowIndex].DataBoundItem, dataGridView1.Columns[e.ColumnIndex].DataPropertyName);
            }


            if (dataGridView1.Columns[e.ColumnIndex].Name == "KeyCode")
            {
                if (e.Value != null && e.Value.ToString().Length > 0)
                {
                    e.Value = new string('*', e.Value.ToString().Length);
                }
            }
        }

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            int i = this.dataGridView1.CurrentCell.ColumnIndex;
            bool usePassword = false;
            if (dataGridView1.Columns[i].Name == "KeyCode")
            {
                usePassword = true;
            }
            TextBox txt = e.Control as TextBox;
            if (txt != null)
            {
                txt.UseSystemPasswordChar = usePassword;
            }
        }

//示例:绑定的源数据类定义
    public class DemoBindClass
    {
        public string Attr { get; set; }

        public string KeyCode { get; set; }

        public DemoDetailA Detail { get; set; }
    }


    public class DemoDetailA
    {
        public string Apro1 { get; set; }

        public string Apro2 { get; set; }

        public string Apro3 { get; set; }

        public DemoDetailB DetailChild { get; set; }
    }


    public class DemoDetailB
    {
        public string Bpro1 { get; set; }

        public string Bpro2 { get; set; }

        public string Bpro3 { get; set; }
    }

绑定到数据源:

            var demo = new[] {
                new DemoBindClass()
                    {
                        Attr = "demo",
                        KeyCode="a123456789b",
                        Detail = new DemoDetailA()
                        {
                            Apro1 = "demoA1",
                            Apro2 = "demoA2",
                            Apro3 = "demoA3",
                            DetailChild = new DemoDetailB()
                            {
                                Bpro1 = "demoB1",
                                Bpro2 = "demoB2",
                                Bpro3 = "demoB3"
                            }
                        }
                    }
            };


            dataGridView1.AutoGenerateColumns = false;
            dataGridView1.DataSource = demo;

兑现钦赐列采用密码框情势展现与编写制定,以及列绑定到复合属性均必要订阅DataGridView的CellFormatting及艾德itingControlShowing事件,并在里边写转换当前Cell的Value,达成列绑定到复合属性,关键点在:伊娃luateValue方法,该措施逻辑非常的粗略,就是依照绑定的习性层级(.分隔)层层遍历获取属性的值,直到遍历完或为空时结束,最后获得的结果便是绑定的属性的值。最后得以实现的成效如下图示:

威尼斯人线上娱乐 1

  

 

一.暗中同意EF生成的接连字符串比较的长和奇妙,若想采纳普通的连接字符串来连…

前言

Contoso 大学示范 Web 应用程序演示怎样行使实体框架(EF)Core 二.0 和
Visual Studio 2017 创造 ASP.NET Core 2.0 MVC Web 应用程序。
演示应用程序是杜撰的Contoso高校的网站。
它总结学生入学,课程创建和老师义务等功用。
那是一星罗棋布教程中的第一章,介绍怎么样初始营造Contoso大学示例应用程序。
下载或查看已做到的应用程序 –
官方。

本连串小说翻译索引目录

EF Core 二.0 是EF的新式版本,但还未曾包蕴全体的 EF 陆.x 功效。 有关 EF 陆.x
和 EF Core 之间什么抉择的新闻,请参阅 EF Core vs.
EF6.x。
假若您选取 EF 陆.x
,请参阅本学科种类的原先版本。

注意事项

  • 对此本课程的 ASP.NET Core 一.一 版本,请参阅PDF格式的入门教程,开发品种小技巧。本课程的 VS
    20壹七 Update
    贰版本。
  • 对于本学科的 Visual Studio 20壹5 版本,请参阅PDF格式的 VS 2015
    版本的 ASP.NET Core
    文档。
    public partial class DataEntities
    {
        private static ConcurrentDictionary<string, string> entityConnStrings = new ConcurrentDictionary<string, string>();

        public DataEntities(string connName)
            : base(BuildEntityConnectionString(connName))
        {

        }

        private static string BuildEntityConnectionString(string connName)
        {

            if (!entityConnStrings.ContainsKey(connName))
            {
                var connStrSetting = System.Configuration.ConfigurationManager.ConnectionStrings[connName];

                EntityConnectionStringBuilder entityConnStrBuilder = new EntityConnectionStringBuilder();
                entityConnStrBuilder.Provider = connStrSetting.ProviderName;
                entityConnStrBuilder.ProviderConnectionString = EncryptUtility.DesDecrypt("XXXXX", connStrSetting.ConnectionString);
                entityConnStrBuilder.Metadata = "res://*/Data.csdl|res://*/Data.ssdl|res://*/Data.msl";
                string entityConnString = entityConnStrBuilder.ToString();
                entityConnStrings.AddOrUpdate(connName, entityConnString, (key, value) => entityConnString);
            }
            return entityConnStrings[connName];
        }
    }
    public partial class DataEntities
    {
        private static ConcurrentDictionary<string, string> entityConnStrings = new ConcurrentDictionary<string, string>();

        public DataEntities(string connName)
            : base(BuildEntityConnectionString(connName))
        {

        }

        private static string BuildEntityConnectionString(string connName)
        {

            if (!entityConnStrings.ContainsKey(connName))
            {
                var connStrSetting = System.Configuration.ConfigurationManager.ConnectionStrings[connName];

                EntityConnectionStringBuilder entityConnStrBuilder = new EntityConnectionStringBuilder();
                entityConnStrBuilder.Provider = connStrSetting.ProviderName;
                entityConnStrBuilder.ProviderConnectionString = EncryptUtility.DesDecrypt("XXXXX", connStrSetting.ConnectionString);
                entityConnStrBuilder.Metadata = "res://*/Data.csdl|res://*/Data.ssdl|res://*/Data.msl";
                string entityConnString = entityConnStrBuilder.ToString();
                entityConnStrings.AddOrUpdate(connName, entityConnString, (key, value) => entityConnString);
            }
            return entityConnStrings[connName];
        }
    }

付出环境

安装如下工具:

  • .NET Core 2.0.0
    SDK
    或更新版本。
  • Visual Studio
    2017
    V15.3 或更高版本,安装 ASP.NET 和 Web 开发工具。

只顾上边的类是一个分部类:partial,同时BuildEntityConnectionString方法是3个静态方法,在BuildEntityConnectionString方法中ProviderConnectionString
= EncryptUtility.DesDecrypt(“XXXXX”,
connStrSetting.ConnectionString);是主要,小编那里是对config中的连接字符串
也都进行了加密,故此处小编索要解密,若无那一个供给可以直接:ProviderConnectionString
=connStrSetting.ConnectionString即可。后续实例化EF上下文对象时,请使用:DataEntities(string
connName)那个协会涵数即可,DataEntities是有血有肉的EF上下文对象,我们的EF上下文类名均只怕不均等。

只顾下边包车型地铁类是贰个分部类:partial,同时BuildEntityConnectionString方法是二个静态方法,在BuildEntityConnectionString方法中ProviderConnectionString
= EncryptUtility.DesDecrypt(“XXXXX”,
connStrSetting.ConnectionString);是主要,小编那里是对config中的连接字符串
也都开始展览了加密,故此处小编供给解密,若无那个必要能够一向:ProviderConnectionString
=connStrSetting.ConnectionString即可。后续实例化EF上下文对象时,请使用:DataEntities(string
connName)那么些布局涵数即可,DataEntities是实际的EF上下文对象,大家的EF上下文类名均或者分歧。

故障排除

尽管蒙受难点,您不或者缓解,平时能够透过将代码与达成的品种展开相比较来找到消除方案。
有关常见错误和消除办法的列表,请参阅本类别最终1个学科的故障排除部分。
如若您未有找到所需的剧情,您也足以在 StackOverflow.com 上发问。

小贴士

本体系涵盖10个科目,每一种教程都建立在早期教程中的基础之上。
在成功做到每一个教程之后,请思虑保存项指标副本。
然后,倘若境遇难点,您能够从上四个学科重新初阶,无需从头初始。

二.接济二个通用对象的XML类别化(即:多个类中有可变类型属性成员,须求分歧的行列结果及变化不相同的行列成分名称),具体落成代码如下:

2.支持三个通用对象的XML种类化(即:二个类中有可变类型属性成员,须求不一致的体系结果及变化区别的行列成分名称),具体完毕代码如下:

Contoso 大学网站运用

学科中塑造的是八个简短的高等学校网址。
用户能够查阅和创新学生,课程和教授音信。 上面是您将要成立的局地页面。

威尼斯人线上娱乐 2

index

威尼斯人线上娱乐 3

edit

网址的 UI 风格与内置模板生成的 UI 风格保持1致,本课程首要关切怎么着运用
Entity Framework。

二个亟待被系列化成XML的类:个中必要扭转的XML元素detail必需有子元素,且子成分名称及子成分内部属性依照项目标不等而分化(即:detail成分下的子元素是可变的)

1个内需被体系化成XML的类:在那之中需要转变的XML成分detail必需有子元素,且子成分名称及子成分内部属性根据项目标两样而分裂(即:detail成分下的子成分是可变的)

创建 ASP.NET Core MVC 网址应用

开拓 Visual Studio 并创制名字为 “ContosoUniversity” 的新 ASP.NET Core C#
web 项目。

  • 从文件菜单中,选用新建>项目。
  • 从左窗格中采取 已安装 -> Visual C# -> Web 。
  • 中档窗格选取 ASP.NET Core Web 应用程序。
  • 输入 ContosoUniversity 作为项目名称,然后单击分明。
![](https://upload-images.jianshu.io/upload_images/4235187-1c7a131da4c70365.png)

newProject
  • 等待 “新建 ASP.NET Core Web 应用程序” 对话框出现
  • 挑选 ASP.NET Core 2.0 和 Web应用程序(模型视图控制器)模板。
  • 注意:本学科要求 ASP.NET Core 二.0 和 EF Core 贰.0 或更高版本 –
    确定保证未采取ASP.NET Core 一.一。
  • 保证认证设置为“不开始展览身份验证”。
  • 单击 “确定” 按钮。

威尼斯人线上娱乐 4

newCore

    [XmlRootAttribute("master")]
    public class DemoMaster<T> where T : class
    {
        [XmlElement("attr")]
        public string DemoAttr { get; set; }

        [XmlElement("detail")]
        public DemoDetail<T> DemoDetail { get; set; } //关键点在这里,该属性元素为:detail,但其子元素根据T不同而不同

    }
    public class DemoDetail<T> : IXmlSerializable where T : class
    {
        public T body { get; set; }

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            string bodyStr = reader.ReadInnerXml();
            this.body = XmlHelper.XmlDeserialize<T>(bodyStr, Encoding.UTF8);
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteRaw(XmlHelper.XmlSerialize(this.body, Encoding.UTF8, true));
        }
    }

    [XmlTypeAttribute("list-a", AnonymousType = false)]
    public class DemoDetailA
    {
        public string Apro1 { get; set; }

        public string Apro2 { get; set; }

        public string Apro3 { get; set; }
    }

    [XmlTypeAttribute("list-b", AnonymousType = false)]
    public class DemoDetailB
    {
        public string Bpro1 { get; set; }

        public string Bpro2 { get; set; }

        public string Bpro3 { get; set; }
    }

    [XmlTypeAttribute("list-c", AnonymousType = false)]
    public class DemoDetailC
    {
        public string Cpro1 { get; set; }

        public string Cpro2 { get; set; }

        public string Cpro3 { get; set; }
    }
    [XmlRootAttribute("master")]
    public class DemoMaster<T> where T : class
    {
        [XmlElement("attr")]
        public string DemoAttr { get; set; }

        [XmlElement("detail")]
        public DemoDetail<T> DemoDetail { get; set; } //关键点在这里,该属性元素为:detail,但其子元素根据T不同而不同

    }
    public class DemoDetail<T> : IXmlSerializable where T : class
    {
        public T body { get; set; }

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(System.Xml.XmlReader reader)
        {
            string bodyStr = reader.ReadInnerXml();
            this.body = XmlHelper.XmlDeserialize<T>(bodyStr, Encoding.UTF8);
        }

        public void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteRaw(XmlHelper.XmlSerialize(this.body, Encoding.UTF8, true));
        }
    }

    [XmlTypeAttribute("list-a", AnonymousType = false)]
    public class DemoDetailA
    {
        public string Apro1 { get; set; }

        public string Apro2 { get; set; }

        public string Apro3 { get; set; }
    }

    [XmlTypeAttribute("list-b", AnonymousType = false)]
    public class DemoDetailB
    {
        public string Bpro1 { get; set; }

        public string Bpro2 { get; set; }

        public string Bpro3 { get; set; }
    }

    [XmlTypeAttribute("list-c", AnonymousType = false)]
    public class DemoDetailC
    {
        public string Cpro1 { get; set; }

        public string Cpro2 { get; set; }

        public string Cpro3 { get; set; }
    }

安装网址样式

简单修改多少个地点,设置站点菜单,布局和主页。
打开 Views/Shared/_Layout.cshtml 文件,进行以下改变:

  • 将3处 “ContosoUniversity” 文字修改为“Contoso University”。
  • 添加 学生、课程、教授和单位菜单,删除联系人菜单。

最首要的修改如下

<html>
......
    <title>@ViewData["Title"] - Contoso University</title>
......
                class="navbar-brand">Contoso University</a>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
                    <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
                    <li><a asp-area="" asp-controller="Students" asp-action="Index">Students</a></li>
                    <li><a asp-area="" asp-controller="Courses" asp-action="Index">Courses</a></li>
                    <li><a asp-area="" asp-controller="Instructors" asp-action="Index">Instructors</a></li>
                    <li><a asp-area="" asp-controller="Departments" asp-action="Index">Departments</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>© 2017 - Contoso University</p>
        </footer>
    </div>
</body>
</html>

在 Views/Home/Index.cshtml 文件,使用以下代码替换文件的内容:

@{
    ViewData["Title"] = "Home Page";
}

<div class="jumbotron">
    <h1>Contoso University</h1>
</div>
<div class="row">
    <div class="col-md-4">
        <h2>Welcome to Contoso University</h2>
        <p>
            Contoso University is a sample application that
            demonstrates how to use Entity Framework Core in an
            ASP.NET Core MVC web application.
        </p>
    </div>
    <div class="col-md-4">
        <h2>Build it from scratch</h2>
        <p>You can build the application by following the steps in a series of tutorials.</p>
        <p><a class="btn btn-default" href="https://docs.asp.net/en/latest/data/ef-mvc/intro.html">See the tutorial »</a></p>
    </div>
    <div class="col-md-4">
        <h2>Download it</h2>
        <p>You can download the completed project from GitHub.</p>
        <p><a class="btn btn-default" href="https://github.com/aspnet/Docs/tree/master/aspnetcore/data/ef-mvc/intro/samples/cu-final">See project source code »</a></p>
    </div>
</div>

按 CTEnclaveL+F五 运转项目或从菜单中选取 调节和测试-> 起始实施(不调试),
您将在浏览器中来看本学科中完毕的首页。

威尼斯人线上娱乐 5

image.png

瞩目上边代码中,供给关爱:德姆oDetail属性及德姆oDetail<T>类,德姆oDetail属性仅是为着生成detail成分节点,而子节点则由德姆oDetail<T>类来进展转移,德姆oDetail<T>是贯彻了IXmlSerializable接口,在XML类别化时,德姆oDetail<T>类仅将body属性对应的T类型实例内容开始展览连串化(WriteRaw),而反类别化时,则先反类别化body属性对应的T类型实例,然后赋值给body属性,那也是高强之处,德姆oDetail<T>类自身并不曾真正参预到种类化中,故系列化的字符串也看不到德姆oDetail<T>类相关的因素,德姆oDetail<T>类仅仅是多个XML体系化格式生成的中介。系列化的XML结果如下:

小心上边代码中,需求关注:德姆oDetail属性及德姆oDetail<T>类,德姆oDetail属性仅是为着生成detail成分节点,而子节点则由德姆oDetail<T>类来展开转变,德姆oDetail<T>是促成了IXmlSerializable接口,在XML种类化时,德姆oDetail<T>类仅将body属性对应的T类型实例内容展开种类化(WriteRaw),而反类别化时,则先反连串化body属性对应的T类型实例,然后赋值给body属性,那也是精粹纷呈之处,德姆oDetail<T>类本人并从未真的参加到连串化中,故种类化的字符串也看不到德姆oDetail<T>类相关的因素,德姆oDetail<T>类仅仅是三个XML体系化格式生成的中介。体系化的XML结果如下:

Entity Framework Core NuGet packages

翻译注: 此标题不翻译好过翻译
要在档次中添加 EF Core 匡助,必要设置相应的数据库达成。本学科使用 SQL
Server 数据库,所急需的次第包 Microsoft.EntityFrameworkCore.SqlServer
已经放手于 Microsoft.AspNetCore.All 包中,因而大家今后如何都不要做。

本条顺序包 (Microsoft.EntityFrameworkCore) 及其依赖项
(Microsoft.EntityFrameworkCore.Relational) 提供了EF运转时帮忙。在稍后的
”数据库迁移“教程中,你将会学习添加二个工具包。

关于可用来 Entity Framework Core 的别的数据库协理程序的新闻,请参阅
Data
Providers。

连串化代码:

类别化代码:

始建数据模型

接下去,您将为Contoso大学应用程序创制实体课程。 您将从以下四个实体初步。

威尼斯人线上娱乐 6

class diagram

在 Student 与 Enrollement 实体间是1个1对多的关系, 在 Course 与
Enrollment 间也设有部分多关联。
换句话说,学生能够参加任意数量的学科,课程能够有私行数量的学员注册。

在以下部分中,您将为每种实体创建三个类。

            var demo1 = new DemoMaster<DemoDetailA>()
            {
                DemoAttr = "demo1",
                DemoDetail = new DemoDetail<DemoDetailA>() { body = new DemoDetailA() { Apro1 = "demoA1", Apro2 = "demoA2", Apro3 = "demoA3" } }
            };

            var demo2 = new DemoMaster<DemoDetailB>()
            {
                DemoAttr = "demo2",
                DemoDetail = new DemoDetail<DemoDetailB>() { body = new DemoDetailB() { Bpro1 = "demoB1", Bpro2 = "demoB2", Bpro3 = "demoB3" } }
            };

            var demo3 = new DemoMaster<DemoDetailC>()
            {
                DemoAttr = "demo3",
                DemoDetail = new DemoDetail<DemoDetailC>() { body = new DemoDetailC() { Cpro1 = "demoC1", Cpro2 = "demoC2", Cpro3 = "demoC3" } }
            };

            textBox1.Text = XmlHelper.XmlSerialize(demo1, Encoding.UTF8);

            textBox1.Text += "\r\n" + XmlHelper.XmlSerialize(demo2, Encoding.UTF8);

            textBox1.Text += "\r\n" + XmlHelper.XmlSerialize(demo3, Encoding.UTF8);
            var demo1 = new DemoMaster<DemoDetailA>()
            {
                DemoAttr = "demo1",
                DemoDetail = new DemoDetail<DemoDetailA>() { body = new DemoDetailA() { Apro1 = "demoA1", Apro2 = "demoA2", Apro3 = "demoA3" } }
            };

            var demo2 = new DemoMaster<DemoDetailB>()
            {
                DemoAttr = "demo2",
                DemoDetail = new DemoDetail<DemoDetailB>() { body = new DemoDetailB() { Bpro1 = "demoB1", Bpro2 = "demoB2", Bpro3 = "demoB3" } }
            };

            var demo3 = new DemoMaster<DemoDetailC>()
            {
                DemoAttr = "demo3",
                DemoDetail = new DemoDetail<DemoDetailC>() { body = new DemoDetailC() { Cpro1 = "demoC1", Cpro2 = "demoC2", Cpro3 = "demoC3" } }
            };

            textBox1.Text = XmlHelper.XmlSerialize(demo1, Encoding.UTF8);

            textBox1.Text += "\r\n" + XmlHelper.XmlSerialize(demo2, Encoding.UTF8);

            textBox1.Text += "\r\n" + XmlHelper.XmlSerialize(demo3, Encoding.UTF8);

Student 实体

在 Models 文件夹中,创设1个名叫 Student.cs
的类公事,并行使以下代码替换模板代码。

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

ID 属性将改成对应数据表的主键。私下认可情形下,Entity Framework 将名称叫 ID
或 {类名}ID 的质量解释为主键。
Enrollments
属性是导航属性。导航属性用于关联其余实体。对于多少个学生实体(数据)来说,当中的
Enrollments 属性包括全体与该学员相关联的 Enrollment
实体(数据)。也便是说,假使数据库中的二个学员行数据涉嫌多个注册行数据(壹对多,在
Enrollment 表中外键关联StudentID 值为该学生的主键值),则 Student
实体中的 Enrollments 导航属性将涵盖那多少个 Enrollment 实体。

如果导航属性可以容纳三个实体(在多对多或一对多涉及中),则其品种必须是足以增进,删除和更新条指标列表,例如ICollection
<T>。您能够内定ICollection <T>或项目,如List
<T>或HashSet <T>。如果内定ICollection
<T>,EF暗中同意创建三个HashSet <T>集合。

连串化的XML:

类别化的XML:

Enrollment 实体

威尼斯人线上娱乐 7

Enrollment

在 Models 文件夹中,创造八个名称为 Student.cs
的类公事,并利用以下代码替换模板代码。

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }

        public Course Course { get; set; }
        public Student Student { get; set; }
    }
}

EnrollmentID 属性将改为主键。本实体使用 {类名}ID 方式代表在 Studnet
实体中央银行使的 ID 情势。 平常你会只选取一种情势,并在全体数据模型中采用。
在此处,区别的情势是为了演示,表达您能够利用任一方式。
在前边的教程中,您将看到怎样行使未有类名的 ID
能够更便于地在数据模型中完成一连。

Grade (等级) 属性是叁个枚举类型。 Grade 类型注解后的 ? 表示
可为空类型。 3个空的级差和八个值为0的级差是例外的 —
空表示等级未知或许未有被赋值。

StudentID 属性是外键,相应的导航属性是 Student。 一个 Enrollment
实体与一个 Student 实体相关联,由此该属性只好拥有保留单个 Studnet
实体(与你事先看到的能够分包多少个注册实体的 Student.Enrollments
导航属性不一样)。

CourseID 属性是外键, 对应的领航属性是 Course。 一个 Enrollment
实体与二个 Course 实体相关联。

当2个属性名称符合形式 <导航属性名><主键名> , EF
将品质解析为外键属性(例如,StudentID 对应 Student 导航属性,因为
Student 实体的主键是 ID)。 外键属性也足以不难地动用
<主键属性名称>(例如,CourseID,因为课程实体的主键是
CourseID)。

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo1</attr>
    <detail><list-a>
    <Apro1>demoA1</Apro1>
    <Apro2>demoA2</Apro2>
    <Apro3>demoA3</Apro3>
</list-a></detail>
</master>

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo2</attr>
    <detail><list-b>
    <Bpro1>demoB1</Bpro1>
    <Bpro2>demoB2</Bpro2>
    <Bpro3>demoB3</Bpro3>
</list-b></detail>
</master>

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo3</attr>
    <detail><list-c>
    <Cpro1>demoC1</Cpro1>
    <Cpro2>demoC2</Cpro2>
    <Cpro3>demoC3</Cpro3>
</list-c></detail>
</master>
<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo1</attr>
    <detail><list-a>
    <Apro1>demoA1</Apro1>
    <Apro2>demoA2</Apro2>
    <Apro3>demoA3</Apro3>
</list-a></detail>
</master>

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo2</attr>
    <detail><list-b>
    <Bpro1>demoB1</Bpro1>
    <Bpro2>demoB2</Bpro2>
    <Bpro3>demoB3</Bpro3>
</list-b></detail>
</master>

<?xml version="1.0" encoding="utf-8"?>
<master>
    <attr>demo3</attr>
    <detail><list-c>
    <Cpro1>demoC1</Cpro1>
    <Cpro2>demoC2</Cpro2>
    <Cpro3>demoC3</Cpro3>
</list-c></detail>
</master>

Course 实体

威尼斯人线上娱乐 8

Course

在 Models 文件夹中,创立1个名称叫 Course.cs
的类公事,并行使以下代码替换模板代码。

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

Enrollments 属性是导航属性。3个 Course 实体能够提到到任意四个
Enrollment 实体。

我们将在本类别的再而三教程中详尽介绍 DatabaseGenerated 天性。
此个性允许你钦定 Course 的主键名,而不是让数据库生成它。

三.winform DataGridView
完毕钦命列选用密码框格局显示与编写制定,以及列绑定到复合属性(即:绑定到多层次属性)
,具体贯彻代码如下:

三.winform DataGridView
达成钦赐列接纳密码框情势突显与编辑,以及列绑定到复合属性(即:绑定到多层次属性),具体完成代码如下:

创造数据库上下文 Database Context

将数据模型与 Entity Framework 功能协同工作的要害类是数据库上下文类。
通过从 Microsoft.EntityFrameworkCore.DbContext 类派生来成立此类。
在代码中,可以钦定数据模型中富含如何实体。 还足以自定义有些 Entity
Framework 行为。 在那些项目中,该类被命名叫 SchoolContext

在档次文件夹中,创设一个名叫Data的文件夹。
在 Data 文件夹中创设三个名叫 SchoolContext.cs
的新类,并用于下代码替换模板代码:

using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Data
{
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Student> Students { get; set; }
    }
}
            dataGridView1.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);
            dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);


        public string EvaluateValue(object obj, string property)
        {
            string retValue = string.Empty;
            string[] names = property.Split('.');

            for (int i = 0; i < names.Count(); i++)
            {
                try
                {
                    var prop = obj.GetType().GetProperty(names[i]);
                    var result = prop.GetValue(obj, null);
                    if (result != null)
                    {
                        obj = result;
                        retValue = result.ToString();
                    }
                    else
                    {
                        break;
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }

            return retValue;
        }


        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {

            if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName.Contains("."))
            {
                e.Value = EvaluateValue(dataGridView1.Rows[e.RowIndex].DataBoundItem, dataGridView1.Columns[e.ColumnIndex].DataPropertyName);
            }


            if (dataGridView1.Columns[e.ColumnIndex].Name == "KeyCode")
            {
                if (e.Value != null && e.Value.ToString().Length > 0)
                {
                    e.Value = new string('*', e.Value.ToString().Length);
                }
            }
        }

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            int i = this.dataGridView1.CurrentCell.ColumnIndex;
            bool usePassword = false;
            if (dataGridView1.Columns[i].Name == "KeyCode")
            {
                usePassword = true;
            }
            TextBox txt = e.Control as TextBox;
            if (txt != null)
            {
                txt.UseSystemPasswordChar = usePassword;
            }
        }

//示例:绑定的源数据类定义
    public class DemoBindClass
    {
        public string Attr { get; set; }

        public string KeyCode { get; set; }

        public DemoDetailA Detail { get; set; }
    }


    public class DemoDetailA
    {
        public string Apro1 { get; set; }

        public string Apro2 { get; set; }

        public string Apro3 { get; set; }

        public DemoDetailB DetailChild { get; set; }
    }


    public class DemoDetailB
    {
        public string Bpro1 { get; set; }

        public string Bpro2 { get; set; }

        public string Bpro3 { get; set; }
    }
            dataGridView1.CellFormatting += new DataGridViewCellFormattingEventHandler(dataGridView1_CellFormatting);
            dataGridView1.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);


        public string EvaluateValue(object obj, string property)
        {
            string retValue = string.Empty;
            string[] names = property.Split('.');

            for (int i = 0; i < names.Count(); i++)
            {
                try
                {
                    var prop = obj.GetType().GetProperty(names[i]);
                    var result = prop.GetValue(obj, null);
                    if (result != null)
                    {
                        obj = result;
                        retValue = result.ToString();
                    }
                    else
                    {
                        break;
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }

            return retValue;
        }


        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {

            if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName.Contains("."))
            {
                e.Value = EvaluateValue(dataGridView1.Rows[e.RowIndex].DataBoundItem, dataGridView1.Columns[e.ColumnIndex].DataPropertyName);
            }


            if (dataGridView1.Columns[e.ColumnIndex].Name == "KeyCode")
            {
                if (e.Value != null && e.Value.ToString().Length > 0)
                {
                    e.Value = new string('*', e.Value.ToString().Length);
                }
            }
        }

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            int i = this.dataGridView1.CurrentCell.ColumnIndex;
            bool usePassword = false;
            if (dataGridView1.Columns[i].Name == "KeyCode")
            {
                usePassword = true;
            }
            TextBox txt = e.Control as TextBox;
            if (txt != null)
            {
                txt.UseSystemPasswordChar = usePassword;
            }
        }

//示例:绑定的源数据类定义
    public class DemoBindClass
    {
        public string Attr { get; set; }

        public string KeyCode { get; set; }

        public DemoDetailA Detail { get; set; }
    }


    public class DemoDetailA
    {
        public string Apro1 { get; set; }

        public string Apro2 { get; set; }

        public string Apro3 { get; set; }

        public DemoDetailB DetailChild { get; set; }
    }


    public class DemoDetailB
    {
        public string Bpro1 { get; set; }

        public string Bpro2 { get; set; }

        public string Bpro3 { get; set; }
    }

利用数据上下文 – 使用重视注入

ASP.NET Core 暗许使用重视注入技术。
服务(如EF数据库上下文)在应用程序运营时期通过依赖注入注册实例。
那2个急需利用劳务的组件通过构造函数参数得到劳动的实例。
稍后大家得以看来控制器构造函数获取上下文实例的代码。

要将 SchoolContext 注册为劳动,请打开 Startup.cs,并依照如下代码修改
ConfigureServices 方法。

//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<SchoolContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddMvc();
}

因此调用 DbContextOptionsBuilder
对象上的措施将接连字符串的名目传递给上下文。 对于本地开发,ASP.NET Core
配置种类从 appsettings.json 文件读取连接字符串。

打开appsettings.json文件并累加3个总是字符串,如下例所示。

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

绑定到数据源:

绑定到数据源:

SQL Server Express LocalDB

一连字符串钦赐 SQL Server LocalDB 数据库。 LocalDB 是 SQL Server Express
数据库引擎的轻量级版本,意在用于应用程序开发,而不是生产用途。 LocalDB
按需运行并以用户情势运转,因而未有复杂的安顿。 默许处境下,LocalDB在
C:/Users/<user> 目录中开创 .mdf 数据库文件。

            var demo = new[] {
                new DemoBindClass()
                    {
                        Attr = "demo",
                        KeyCode="a123456789b",
                        Detail = new DemoDetailA()
                        {
                            Apro1 = "demoA1",
                            Apro2 = "demoA2",
                            Apro3 = "demoA3",
                            DetailChild = new DemoDetailB()
                            {
                                Bpro1 = "demoB1",
                                Bpro2 = "demoB2",
                                Bpro3 = "demoB3"
                            }
                        }
                    }
            };


            dataGridView1.AutoGenerateColumns = false;
            dataGridView1.DataSource = demo;
            var demo = new[] {
                new DemoBindClass()
                    {
                        Attr = "demo",
                        KeyCode="a123456789b",
                        Detail = new DemoDetailA()
                        {
                            Apro1 = "demoA1",
                            Apro2 = "demoA2",
                            Apro3 = "demoA3",
                            DetailChild = new DemoDetailB()
                            {
                                Bpro1 = "demoB1",
                                Bpro2 = "demoB2",
                                Bpro3 = "demoB3"
                            }
                        }
                    }
            };


            dataGridView1.AutoGenerateColumns = false;
            dataGridView1.DataSource = demo;
丰硕代码,使用测试数据初步化数据库

EF 将为你创设三个空数据库。
在本节中,您将编写制定三个成立数据库后调用的方法,以便利用测试数据开始展览填空。

在那里,您将应用 EnsureCreated 方法自动制造数据库。
在前面包车型客车教程中,您将见到怎么样运用 Code First Migration (代码优先迁移)
来更改数据库架构而不是删除和再一次创制数据库来拍卖架构更改。

Data 文件夹中,创制二个名叫 DbInitializer.cs
的新类文件,并行使以下代码替换模板代码,那些代码将在要求时创设数据库,并将测试数据加载到新数据库中。

//DbInitializer.cs

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Data
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            context.Database.EnsureCreated();

            // Look for any students.
            if (context.Students.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
            new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
            new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
            };
            foreach (Student s in students)
            {
                context.Students.Add(s);
            }
            context.SaveChanges();

            var courses = new Course[]
            {
            new Course{CourseID=1050,Title="Chemistry",Credits=3},
            new Course{CourseID=4022,Title="Microeconomics",Credits=3},
            new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
            new Course{CourseID=1045,Title="Calculus",Credits=4},
            new Course{CourseID=3141,Title="Trigonometry",Credits=4},
            new Course{CourseID=2021,Title="Composition",Credits=3},
            new Course{CourseID=2042,Title="Literature",Credits=4}
            };
            foreach (Course c in courses)
            {
                context.Courses.Add(c);
            }
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
            new Enrollment{StudentID=3,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
            new Enrollment{StudentID=6,CourseID=1045},
            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };
            foreach (Enrollment e in enrollments)
            {
                context.Enrollments.Add(e);
            }
            context.SaveChanges();
        }
    }
}

代码检查数据库中是还是不是有上学的儿童,若是没有,则只要数据库是新的,并且供给利用测试数据开始展览种子。它将测试数据加载到数组而不是
List <T> 集合来优化品质。

在Program.cs中,修改Main方法在应用程序运维时执行以下操作:

  • 从依赖注入容器获取数据库上下文实例。
  • 调用种子方法,传递给它的上下文。
  • 种子方法成功时销毁上下文。

public static void Main(string[] args)
{
    var host = BuildWebHost(args);

    using (var scope = host.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<SchoolContext>();
            DbInitializer.Initialize(context);
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while seeding the database.");
        }
    }

    host.Run();
}

在较旧的科目中,您或者会在Startup.cs中的Configure方法中观察类似的代码。
大家提议您仅使用Configure方法来安装请求管道。
应用程序运行代码属于Main方法。

第一回运营应用程序时,将创建数据库并植入测试数据。
无论哪一天转移数据模型,都能够去除数据库,更新种子方法,并以新的数据库重新开始重复启航。
在后头的科目中,您将见到在数据模型更改时怎么着修改数据库,而不删除和另行创建它。

达成钦定列接纳密码框格局展现与编辑,以及列绑定到复合属性均必要订阅DataGridView的CellFormatting及艾德itingControlShowing事件,并在里头写转换当前Cell的Value,完成列绑定到复合属性,关键点在:伊娃luateValue方法,该措施逻辑很简单,就是依照绑定的习性层级(.分隔)层层遍历获取属性的值,直到遍历完或为空时甘休,最终取得的结果便是绑定的属性的值。最后兑现的成效如下图示:

达成钦赐列采纳密码框形式展现与编写制定,以及列绑定到复合属性均须求订阅DataGridView的CellFormatting及艾德itingControlShowing事件,并在里边写转换当前Cell的Value,达成列绑定到复合属性,关键点在:伊娃luateValue方法,该方法逻辑很简单,正是依照绑定的性质层级(.分隔)层层遍历获取属性的值,直到遍历完或为空时结束,最后收获的结果便是绑定的属性的值。最后达成的服从如下图示:

创立控制器和视图

接下去,您将应用 Visual Studio 脚手架加上 MVC 控制器和视图,并选取 EF
来查询和保留数据。

机动创造CRUD操作方法和视图称为脚手架。
脚手架与代码生成器分歧之处在于,脚手架代码只是基础代码,您能够依照本身的必要开始展览修改,而平凡情状下,您不会修改生成器生成的代码。
当您要求自定义生成器生成的代码,能够利用部分类,可能在情景时有爆发转移时时重新生成代码。

  • 右键单击化解方案资源管理器中的 Controllers 文件夹,然后接纳 添加
    -> 控制器。
  • 在“添加基架”对话框中,接纳“视图使用 Entity Framework 的 MVC
    控制器”,点击“添加”
  • 在“添加控制器”对话框中:
    • 模型类选用 Student
    • 多少上下文类选用 SchoolContext
    • 点击 “添加”。

威尼斯人线上娱乐 9

new Controller

当您单击添加时,Visual Studio 脚手架引擎创立贰个 StudentsController.cs
文件和1组与控制器一起使用的视图(.cshtml文件)。

(脚手架引擎仍是可以够为你创造数据库上下文,要是您不像以前在本教程中那样手动创设它。
您能够透过单击数据上下文类左边的加号在“添加控制器”框中钦定新的上下文类。
然后Visual Studio将开创您的DbContext类以及控制器和视图。)

你会小心到控制器将2个 SchoolContext 作为三个构造函数参数。

namespace ContosoUniversity.Controllers
{
    public class StudentsController : Controller
    {
        private readonly SchoolContext _context;

        public StudentsController(SchoolContext context)
        {
            _context = context;
        }

ASP.NET 注重注入负责将 SchoolContext 的二个实例传递到控制器中。
前文中,已经
在 Startup.cs 文件中配备 SchoolContext 的借助注入。

控制器包含1个 Index 方法,用于体现数据库中的全部学员。
该措施通过读取数据库上下文实例的 Students
属性获取学生实体集中的学员列表:

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}

稍后将介绍此代码中的异步编制程序知识。

视图 Views/Students/Index.cshtml 使用 HTML 表格呈现学生列表。
(此处未对脚手架生成的代码进行别的修改,不再贴代码占用小说篇幅。 )

按 CTHavalL + F伍 运维项目或从菜单中选取 调节和测试 -> 开首实践(不调节和测试)。

单击 Student 链接,能够看到 DbInitializer.Initialize
方法中插入的测试数据。 依照浏览器窗口的窄小程度,您晤面到页面顶部的
Student
链接,也有十分的大希望你必须单击右上角的领航空图标才能收看隐藏菜单中的链接。

威尼斯人线上娱乐 10

narrow Page

威尼斯人线上娱乐 11

sdudent index

威尼斯人线上娱乐 12

威尼斯人线上娱乐 13

查看数据库

当你运营应用程序时,DbInitializer.Initialize 方法调用 EnsureCreated 。
EF 看到未有数据库,所以它创设了四个,然后 Initialize
方法代码的其他部分用数码填充数据库。 在 Visual Studio 中,您能够运用 SQL
Server 对象能源管理器(SSOX)查看数据库。

万1 SSOX 窗口未有打开,在 Visual Studio 中,点击菜单 “视图” -> “SQL
Server 对象财富管理器”。
在 SSOX 中,单击(localdb)\ MSSQLLocalDB > 数据库,然后单击
ContosoUniversity1,也便是大家前面在 appsettings.json
文件中设置的连接字符串中数据库名称。
进展“表”节点以查看数据库中的表。

威尼斯人线上娱乐 14

ssox

右键单击 Student 表,然后单击 “查看数据”
以查看已开立的列和插入到表中的数据行。

威尼斯人线上娱乐 15

student table

.mdf 和.ldf 数据库文件位于C:\Users<你的用户名> 文件夹中。
因为你在应用程序运维时运转的开首化程序方法中调用 EnsureCreated
,所以今后得以更改 Student
类,删除数据库,再一次运转应用程序,并自行重新创制数据库以卓殊您的改动。
例如,倘诺你将 EmailAddress 属性添加到 Student
类,则会在再度成立的表中看到贰个新的EmailAddress 列。

四.运用BCP(sqlbulkcopy)来兑现多少个不相同数据库之间举办数量差异传输(即:数据同步)

④.应用BCP(sqlbulkcopy)来完结多少个不等数据库之间展开数据差异传输(即:数据同步)

约定

基于约定优于配备的尺码,Entity Framework
创设一个数据库时,你所需书写的代码很少。

  • DbSet 属性的名目作为表名。
    对于未由DbSet属性引用的实业,实体类名用作表名。

  • 实体性质名称用于列名。

  • 名称为 ID 或 classnameID 的实体性质被辨认为主键属性。

  • 应用 导航属性名+实体主键名 命名的品质,会被自动识别为外键,例如:
    StudentID 由 Student (导航属性) + ID (Student实体主键名
    )组成。外键也得以总结只行使实体主键名,例如 EnrollmentID (外键) 与
    EnrollmentID (Enrollment 实体的主键)。

预约能够被掩盖。例如,你能够显式内定表名,如本学科前边所观察的。
您能够设置列名称并将别的性质设置为主键或外键,那将在后面包车型客车科目中聊到。

TransferBulkCopy功能:完毕多少个不等数据库之间开始展览多少差距传输,BuildInsertOrUpdateToDestTableSql成效:依照目标表及一时表生成更新与插入记录的SQL语句,以此完结:若同步的数目已存在,则更新,不存在,则插入。

TransferBulkCopy成效:达成四个不等数据库之间开始展览多少差异传输,BuildInsertOrUpdateToDestTableSql功用:依照目标表及一时半刻表生成更新与插入记录的SQL语句,以此完结:若同步的数额已存在,则更新,不设有,则插入。

异步代码

ASP.NET Core和EF Core的暗中同意使用异步编制程序。

Web
服务器的可用线程数量有限,在高负荷景况下,全部可用线程都恐怕都在运用。
当爆发这种情景时,服务器不恐怕处理新的呼吁,直到线程被假释。
使用同步代码时,许八线程恐怕会被绑定,而实际上它们并未有做其余工作,因为它们正在等候
I/O 达成。 使用异步代码,当进程正在守候I/O
完结时,其线程将被释放,供服务器用于拍卖任何请求。
因而,异步代码能够更管用地运用服务器能源,并且使服务器能够无延迟地处理更加多流量。

异步代码在运作时引入了少量的开发,不过对于低流量景况,品质降低能够忽略不计,而对于高流量境况,潜在的属性升高是伟人的。
在以下代码中,async 关键字, Task<T> 再次来到值,await 关键字和
ToListAsync 方法共同组成异步执行代码。

public async Task<IActionResult> Index()
{
    return View(await _context.Students.ToListAsync());
}
  • async 关键字告诉编写翻译器为格局体生成回调函数,并活动创立再次回到的
    Task <IActionResult> 对象。

  • 重临类型 Task<IActionResult> 表示正在开展的工作,其结果类型为
    IActionResult

  • await 关键字告诉编写翻译器将该措施分为两有的。
    第三有的以异步运维的操作甘休。
    第一局地被放入回调方法,该操作在操作实现时被调用。

  • ToListAsyncToList 扩张方法的异步版本。

当你编写使用实体框架的异步代码时,须求专注的壹些作业:

  • 唯有会掀起查询或将下令发送到数据库的语句才须求异步执行。 那包蕴诸如
    ToListAsyncSingleOrDefaultAsyncSaveChangesAsync
    它不应有包含,例如,只是改变IQueryable的语句,类似
    var students = context.Students.Where(s => s.LastName == "Davolio")
    那样的言语。

  • EF上下文不是线程安全的:不要品味并行执行几个操作。 当您调用任何异步
    EF 方法时,请始终使用 await 关键字。

  • 设若你想行使异步代码的品质优势,请确认保证您正在使用的别样库包(例如用于分页)也运用异步,如果他们调用任何导致查询发送到数据库的格局。

有关.NET中异步编制程序的越来越多音讯,请参阅 Async
Overview。

        /// <summary>
        /// 通用数据传输方法(采用SqlBulkCopy快速批量插入,然后再进行处理)
        /// </summary>
        /// <param name="sourceSelectSql"></param>
        /// <param name="sourceConn"></param>
        /// <param name="destTableName"></param>
        /// <param name="destConn"></param>
        /// <param name="colMapFunc"></param>
        /// <param name="lastSaveAction"></param>
        public void TransferBulkCopy(string sourceSelectSql, SqlConnection sourceConn, string destTableName, SqlConnection destConn, Func<DataTable, Dictionary<string, string>> colMapFunc,
                                    Func<string, DataTable, SqlConnection, SqlConnection, bool> lastSaveAction, bool closeConnection = true)
        {
            DataTable srcTable = new DataTable();
            SqlDataAdapter srcAdapter = new SqlDataAdapter(sourceSelectSql, sourceConn);
            srcAdapter.AcceptChangesDuringUpdate = false;
            SqlCommandBuilder srcCmdBuilder = new SqlCommandBuilder(srcAdapter);
            srcAdapter.Fill(srcTable);

            if (srcTable != null && srcTable.Rows.Count > 0)
            {
                string tempDestTableName = "#temp_" + destTableName;
                ClsDatabase.gExecCommand(destConn, string.Format("select top 0 * into {0}  from  {1}", tempDestTableName, destTableName), false);
                List<string> mapDestColNameList = new List<string>();
                using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(destConn))
                {
                    sqlBulkCopy.DestinationTableName = tempDestTableName;
                    foreach (var map in colMapFunc(srcTable))
                    {
                        sqlBulkCopy.ColumnMappings.Add(map.Key, map.Value);
                        mapDestColNameList.Add(map.Value);
                    }
                    sqlBulkCopy.WriteToServer(srcTable);
                }
                srcTable.ExtendedProperties.Add(MapDestColNames_String, mapDestColNameList);
                bool needUpdate = lastSaveAction(tempDestTableName, srcTable, destConn, sourceConn);

                if (needUpdate)
                {
                    if (srcTable.Columns.Contains("TranFlag"))
                    {
                        foreach (DataRow row in srcTable.Rows)
                        {
                            row["TranFlag"] = true;
                        }
                    }
                    srcAdapter.Update(srcTable);
                }

            }

            if (closeConnection)
            {
                DisposeConnections(sourceConn, destConn);
            }
        }
        /// <summary>
        /// 通用数据传输方法(采用SqlBulkCopy快速批量插入,然后再进行处理)
        /// </summary>
        /// <param name="sourceSelectSql"></param>
        /// <param name="sourceConn"></param>
        /// <param name="destTableName"></param>
        /// <param name="destConn"></param>
        /// <param name="colMapFunc"></param>
        /// <param name="lastSaveAction"></param>
        public void TransferBulkCopy(string sourceSelectSql, SqlConnection sourceConn, string destTableName, SqlConnection destConn, Func<DataTable, Dictionary<string, string>> colMapFunc,
                                    Func<string, DataTable, SqlConnection, SqlConnection, bool> lastSaveAction, bool closeConnection = true)
        {
            DataTable srcTable = new DataTable();
            SqlDataAdapter srcAdapter = new SqlDataAdapter(sourceSelectSql, sourceConn);
            srcAdapter.AcceptChangesDuringUpdate = false;
            SqlCommandBuilder srcCmdBuilder = new SqlCommandBuilder(srcAdapter);
            srcAdapter.Fill(srcTable);

            if (srcTable != null && srcTable.Rows.Count > 0)
            {
                string tempDestTableName = "#temp_" + destTableName;
                ClsDatabase.gExecCommand(destConn, string.Format("select top 0 * into {0}  from  {1}", tempDestTableName, destTableName), false);
                List<string> mapDestColNameList = new List<string>();
                using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(destConn))
                {
                    sqlBulkCopy.DestinationTableName = tempDestTableName;
                    foreach (var map in colMapFunc(srcTable))
                    {
                        sqlBulkCopy.ColumnMappings.Add(map.Key, map.Value);
                        mapDestColNameList.Add(map.Value);
                    }
                    sqlBulkCopy.WriteToServer(srcTable);
                }
                srcTable.ExtendedProperties.Add(MapDestColNames_String, mapDestColNameList);
                bool needUpdate = lastSaveAction(tempDestTableName, srcTable, destConn, sourceConn);

                if (needUpdate)
                {
                    if (srcTable.Columns.Contains("TranFlag"))
                    {
                        foreach (DataRow row in srcTable.Rows)
                        {
                            row["TranFlag"] = true;
                        }
                    }
                    srcAdapter.Update(srcTable);
                }

            }

            if (closeConnection)
            {
                DisposeConnections(sourceConn, destConn);
            }
        }


        /// <summary>
        /// 生成同步插入及更新目的表SQL语句
        /// </summary>
        /// <param name="destTableName"></param>
        /// <param name="tempdestTableName"></param>
        /// <param name="pkWhere"></param>
        /// <param name="mapDestColNames"></param>
        /// <returns></returns>
        public string BuildInsertOrUpdateToDestTableSql(string destTableName, string tempdestTableName, string[] pkWhereColNames, object mapDestColNames)
        {
            var mapDestColNameList = mapDestColNames as List<string>;
            string updateColNames = null;
            foreach (string col in mapDestColNameList)
            {
                if (!pkWhereColNames.Contains(col, StringComparer.OrdinalIgnoreCase))
                {
                    updateColNames += string.Format(",{0}=tnew.{0}", col);
                }
            }
            updateColNames = updateColNames.Substring(1);
            string insertColNames = string.Join(",", mapDestColNameList);

            string pkWhereSql = null;
            foreach (string col in pkWhereColNames)
            {
                pkWhereSql += string.Format("and told.{0}=tnew.{0}", col);
            }
            pkWhereSql = pkWhereSql.Substring(3);

            StringBuilder sqlBuilder = new StringBuilder();
            sqlBuilder.AppendFormat("UPDATE {0}  SET {1} FROM {0} told INNER JOIN {2} tnew ON {3}  " + Environment.NewLine,
                                    destTableName, updateColNames, tempdestTableName, pkWhereSql);
            sqlBuilder.AppendFormat("INSERT INTO {0}({1}) SELECT {1} FROM {2} tnew WHERE NOT EXISTS(SELECT 1 FROM {0} told WHERE {3}) " + Environment.NewLine,
                                    destTableName, insertColNames, tempdestTableName, pkWhereSql);

            return sqlBuilder.ToString();

        }

小结

您以后创办了几个简便的应用程序,使用 Entity Framework Core 和 SQL Server
Express LocalDB 存款和储蓄和体现数据。 在底下的科目中,您将学习怎么着执行基本的
CRUD(创造,读取,更新和删除)操作。

 

应用示例如下:

        /// <summary>
        /// 生成同步插入及更新目的表SQL语句
        /// </summary>
        /// <param name="destTableName"></param>
        /// <param name="tempdestTableName"></param>
        /// <param name="pkWhereColNames"></param>
        /// <param name="mapDestColNames"></param>
        /// <param name="sqlType">0=生成INSERT与UPDATE;1=生成UPDATE语句;2=生成INSERT语句</param>
        /// <returns></returns>
        public string BuildInsertOrUpdateToDestTableSql(string destTableName, string tempdestTableName, string[] pkWhereColNames, object mapDestColNames, int sqlType = 0)
        {
            var mapDestColNameList = mapDestColNames as List<string>;
            string updateColNames = null;
            foreach (string col in mapDestColNameList)
            {
                if (!pkWhereColNames.Contains(col, StringComparer.OrdinalIgnoreCase))
                {
                    updateColNames += string.Format(",{0}=tnew.{0}", col);
                }
            }
            updateColNames = updateColNames.Substring(1);
            string insertColNames = string.Join(",", mapDestColNameList);

            string pkWhereSql = null;
            foreach (string col in pkWhereColNames)
            {
                pkWhereSql += string.Format(" and told.{0}=tnew.{0} ", col);
            }
            pkWhereSql = pkWhereSql.Trim().Substring(3);

            StringBuilder sqlBuilder = new StringBuilder();

            if (sqlType == 0 || sqlType == 1)
            {
                sqlBuilder.AppendFormat("UPDATE {0}  SET {1} FROM {0} told INNER JOIN {2} tnew ON {3}  " + Environment.NewLine,
                                        destTableName, updateColNames, tempdestTableName, pkWhereSql);
            }

            if (sqlType == 0 || sqlType == 2)
            {
                sqlBuilder.AppendFormat("INSERT INTO {0}({1}) SELECT {1} FROM {2} tnew WHERE NOT EXISTS(SELECT 1 FROM {0} told WHERE {3}) " + Environment.NewLine,
                                        destTableName, insertColNames, tempdestTableName, pkWhereSql);

            }

            return sqlBuilder.ToString();

        }
        public void SendData_CustomerAuthorization()
        {
            try
            {
                SqlConnection obConnLMS1 = new SqlConnection(master.connLMSStr);
                SqlConnection obConnWEB1 = new SqlConnection(master.connWEBStr);

                string selectSql = @"SELECT TOP {0} Id,Phone,Mac,IsSet,LastLoginTime,PCName,TranFlag FROM TWEB_CustomerAuthorization WHERE TranFlag=0 ORDER BY Id ";

                selectSql = string.Format(selectSql, master.batchSize);

                master.TransferBulkCopy(selectSql, obConnWEB1,
                                "TB_CustomerAuthorization", obConnLMS1,
                                 (stable) =>
                                 {
                                     var colMaps = new Dictionary<string, string>();
                                     foreach (DataColumn col in stable.Columns)
                                     {
                                         if (!col.ColumnName.Equals("TranFlag", StringComparison.OrdinalIgnoreCase))
                                         {
                                             colMaps.Add(col.ColumnName, col.ColumnName);
                                         }
                                     }
                                     return colMaps;
                                 },
                                 (tempTableName, stable, destConn, srcConn) =>
                                 {
                                     StringBuilder saveSqlBuilder = new StringBuilder("begin tran" + Environment.NewLine);

                                     string IUSql = master.BuildInsertOrUpdateToDestTableSql("TB_CustomerAuthorization", tempTableName, new[] { "Id" }, stable.ExtendedProperties[master.MapDestColNames_String]);
                                     saveSqlBuilder.Append(IUSql);

                                     saveSqlBuilder.AppendLine("commit");

                                     ClsDatabase.gExecCommand(destConn, saveSqlBuilder.ToString());

                                     master.WriteMsg(master.lstSended, string.Format("上传时间:{0:yyyy-MM-dd HH:mm}\t SendData_CustomerAuthorization \t Succeed:{1}", DateTime.Now, stable.Rows.Count));

                                     return true;

                                 });
            }
            catch (Exception ex)
            {
                master.WriteMsg(master.lstErrorInfo, DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "\t" + "SendData_CustomerAuthorization" + "\t" + ex.Message.ToString());
            }
        }

  

一同原理如下:

 

1.定义好查询源服务器的内需1块的表(一般表中我们定义一个用于是或不是同步的标识字段,如:TranFlag
Bit类型,0象征新数据,未共同,1代表已联合);

运用示例如下:

贰.查询源服务器的急需共同的表的记录(一般是TranFlag=0的记录),利用SqlDataAdapter+SqlCommandBuilder
装载Dataset,目标是继承能够利用SqlDataAdapter直接扭转更新命令并施行;

        public void SendData_CustomerAuthorization()
        {
            try
            {
                SqlConnection obConnLMS1 = new SqlConnection(master.connLMSStr);
                SqlConnection obConnWEB1 = new SqlConnection(master.connWEBStr);

                string selectSql = @"SELECT TOP {0} Id,Phone,Mac,IsSet,LastLoginTime,PCName,TranFlag FROM TWEB_CustomerAuthorization WHERE TranFlag=0 ORDER BY Id ";

                selectSql = string.Format(selectSql, master.batchSize);

                master.TransferBulkCopy(selectSql, obConnWEB1,
                                "TB_CustomerAuthorization", obConnLMS1,
                                 (stable) =>
                                 {
                                     var colMaps = new Dictionary<string, string>();
                                     foreach (DataColumn col in stable.Columns)
                                     {
                                         if (!col.ColumnName.Equals("TranFlag", StringComparison.OrdinalIgnoreCase))
                                         {
                                             colMaps.Add(col.ColumnName, col.ColumnName);
                                         }
                                     }
                                     return colMaps;
                                 },
                                 (tempTableName, stable, destConn, srcConn) =>
                                 {
                                     StringBuilder saveSqlBuilder = new StringBuilder("begin tran" + Environment.NewLine);

                                     string IUSql = master.BuildInsertOrUpdateToDestTableSql("TB_CustomerAuthorization", tempTableName, new[] { "Id" }, stable.ExtendedProperties[master.MapDestColNames_String]);
                                     saveSqlBuilder.Append(IUSql);

                                     saveSqlBuilder.AppendLine("commit");

                                     ClsDatabase.gExecCommand(destConn, saveSqlBuilder.ToString());

                                     master.WriteMsg(master.lstSended, string.Format("上传时间:{0:yyyy-MM-dd HH:mm}\t SendData_CustomerAuthorization \t Succeed:{1}", DateTime.Now, stable.Rows.Count));

                                     return true;

                                 });
            }
            catch (Exception ex)
            {
                master.WriteMsg(master.lstErrorInfo, DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "\t" + "SendData_CustomerAuthorization" + "\t" + ex.Message.ToString());
            }
        }

3.选择insert
into从指标服务器的将被联合的表复制结构发生贰个一时半刻表,表名1般是:#temp_指标服务器的将被一道表名
,那样权且表与实体表的协会完全1致;

手拉手原理如下:

四.实例化一个SqlBulkCopy,并确立源服务器的须要共同的表字段与指标一时表字段的投射,然后实施跨服务器传输;

肆.一.概念好查询源服务器的内需1起的表(壹般表中大家定义一个用于是不是同步的标识字段,如:TranFlag
Bit类型,0象征新数据,未共同,壹代表已联合);

五.采纳 BuildInsertOrUpdateToDestTableSql 方法 ,生成
 目标服务器的将被一块的表 与
一时半刻表的插入与更新SQL语句(现在在同贰个库了,想怎么用SQL语句均可)  

4.贰.查询源服务器的内需共同的表的笔录(壹般是TranFlag=0的笔录),利用SqlDataAdapter+SqlCommandBuilder
装载Dataset,指标是持续能够动用SqlDataAdapter直接扭转更新命令并实施;

陆.为力保壹致性,故外层还需包裹事务SQL语句,若还需参加其它处理SQL,可以加在begin
tran  …
commit代码块中即可,最终执行SQL语句:gExecCommand(ClsDatabase.gExecCommand是一个SQLDB
HELPE宝马X3 类的推行SQL命令的措施)

4.3.选用insert
into从目标服务器的将被同台的表复制结构发生三个一时表,表名1般是:#temp_目标服务器的将被壹并表名
,那样一时表与实体表的布局完全一致;

 

四.4.实例化3个SqlBulkCopy,并树立源服务器的急需一块的表字段与目标一时半刻表字段的映射,然后实施跨服务器传输;

四.5.接纳 BuildInsertOrUpdateToDestTableSql 方法 ,生成
 指标服务器的将被同台的表 与
一时半刻表的插入与更新SQL语句(未来在同一个库了,想怎么用SQL语句均可)  

4.6.为力保一致性,故外层还需包裹事务SQL语句,若还需插足此外处理SQL,能够加在begin
tran  …
commit代码块中即可,最终执行SQL语句:gExecCommand(ClsDatabase.gExecCommand是三个SQLDB
HELPERubicon 类的履行SQL命令的办法)

 

5.实现同3个WINDOWS SE锐界VICE程序
COPY多份,然后通过改变自定义的服务ID(瑟维斯ID)配置项来达成:同三个服务程序安装成多个分化的WINDOWS服务进度:

伍.一.创造1个WINDOWS服务项目,在ProjectInstaller设计器界面通过右键弹出菜谱选拔安装程序(serviceProcessInstaller一、serviceInstaller一)、并安装好ServiceName、DisplayName、Description、Account等,如下图示:

威尼斯人线上娱乐 16

5.二.在ProjectInstaller构造函数中追加从CONFIG文件中读取自定义的劳动ID(ServiceID)配置项的值,然后将ServiceID拼加到预设的ServiceName前面,以便实际依据ServiceID能够设置成分化ServiceID后缀的劳务进程,关键点在于改变ServiceName,另二个关键点是从CONFIG文件中获得瑟维斯ID,由于设置时,守旧的不二等秘书诀不能平常读取到CONFIG,只可以通过Assembly.GetExecutingAssembly().Location
来获取当前实施的次序集的门径再拼成CONFIG文件路径,最终读出瑟维斯ID的值,示例代码如下:

    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();

            string assyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
            string assyCfgPath = assyLocation + ".config";
            string installServiceLogPath = Path.Combine(Path.GetDirectoryName(assyLocation), "InstallServiceLog.log");

            string serviceID = ConfigUtil.GetAppSettingValueForConfigPath("ServiceID", assyCfgPath);

            System.IO.File.AppendAllText(installServiceLogPath, string.Format("[{0:yyyy-MM-dd HH:mm:ss}] ServiceAssembly ConfigPath:{1};\r\n", DateTime.Now, assyCfgPath));

            if (!string.IsNullOrWhiteSpace(serviceID))
            {
                this.serviceInstaller1.DisplayName = "TestService_" + serviceID;
                this.serviceInstaller1.ServiceName = "TestService_" + serviceID;
            }

            System.IO.File.AppendAllText(installServiceLogPath, string.Format("[{0:yyyy-MM-dd HH:mm:ss}] ProjectInstaller.ProjectInstaller() ->ServiceID:{1},ServiceName:{2}; \r\n", DateTime.Now, serviceID, this.serviceInstaller1.ServiceName));
        }
    }

五.三.在服务类的构造函数中①律扩张从CONFIG中读取自定义的劳务ID(ServiceID)配置项的值,然后将ServiceID拼加到预设的ServiceName后边(注意应与上述ProjectInstaller中钦赐的ServiceName相同),示例代码如下:  

public partial class TestService: ServiceBase
{
     public TestService()
    {
          serviceID = ConfigUtil.GetAppSettingValue("ServiceID");
            if (!string.IsNullOrWhiteSpace(serviceID))
            {
                this.ServiceName = "TestService_" + serviceID;
            }
    }

}

 上述三步就马到功成了同一个服务程序安装成四个不一样的WINDOWS服务进度,这么些照旧相比较实用的啊!上述ConfigUtil是包裹的3个安插文件读写帮忙类,以前小说有介绍,后面也会揭露叁个更完整的ConfigUtil类。


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图