返回首页

{A}{S0}

{S2}简介
Widgetsphere NHydrate ORM生成器是一个工具,模型驱动平台开发,以填补差距。它可以让你设计一个模型,并产生从你的框架模型包括数据库架构,数据库中的静态数据,数据访问层,数据传输层,单元测试,和数据库安装/升级库。
REST的功能是新的,因为是数据传输层和服务。这是正在更新所有的时间,所以请经常更新。映射类
ORM工具的主要目的是为了图一个CRUD层从数据库到一个易于使用的API。您可以通过现有的数据库建设从无到有或逆向工程模型。一旦你有一个模型,它是您的主副本。你不应该胡乱数据库更改。所有变化模型,并重新生成。所有您的数据库模式发生变化,应体现在生成和自定义的数据库脚本。这确保了连续性,并允许您升级您的数据库和API的不同版本的系统。
你的第一个模型,将反映您的数据库架构。概念化模型一旦你,你就可以开始更先进的修改如下所述。项目
当一个模型生成,6个项目在VS.NET创建。生成的第一个项目为核心的DAL。它包含你的数据库的所有对象和集合。然后创建的DTO层。此镜的DAL,但与轻量级对象序列化功能综合查询电线。第三个项目是DTO映射库。这是使用数据服务,地图DAL的DTO层。第四个项目是数据服务本身。这个服务是用来处理通过网络发送的DTO的容器。第五个项目是单元测试。这些测试可以创建一个数据库,并插入,更新和删除信息,以确保您的模型参照完整性。最后的项目是安装库。您可以运行。NET安装的实用程序或包含在一个更大的应用程序向用户提供安装能力。数据访问层
DAL的是系统的核心。它包含了该模型的具体类。这些类可以加载并保存到数据库,以及有继承层次结构。他们可以查询LINQ语法和关于他们的一切都是强类型的。这是唯一生成的库,需要在客户端上,数据库访问。它仅是为所有的数据访问的看门人。它实现了加载的实体和逻辑,节能,继承等,这个库是可扩展的所有类产生部分分为两个不同的文件类别。有一个用户文件生成一次并不会被覆盖,和一台机器发电机和管理的文件将被覆盖。有没有需要保持跟踪发生器将覆盖或保护的地区,像很多ORM应用,。这种哲学是混乱的,而且容易出错。您的自定义代码将永远不会被改写。它是直接编译到相关实体和编译库的用户没有办法知道自定义和生成的代码之间的差异。数据传输层
数据传输层的POCO对象,允许本地JSON和XML序列化的对象通过线路设置。这可以用来在数据服务提供的REST接口。这些对象可以被用来作为财产容器传递给外观层或其他层体系结构的直接数据库访问是没有必要或限制。它们被用来生成的框架内为REST有用服务的基础。数据传输测绘项目
数据传输库,没有其他目的,但映射DTO层的DAL层。它是用来生成的Web服务执行与DAL双向的存储和检索操作。这个库是与DAL和的DTO的服务器副本在服务器上使用。数据服务项目
数据服务器是一个生成的Web服务,可以使用同一个数据库跨线接口。有没有需要添加任何自定义代码得到它运行。这是一个有用REST的服务,可以直接暴露对象与JSON和XML对象到脚本的网页。安装工程
安装项目包含了所有的代码来创建一个新的数据库或更新现有的。当创建一个新的数据库,创建的所有表,存储过程,索引,关系,和静态数据。该数据库是由DAL。每个数据库创建或修改后版本。安装应用程序确定当前版本的数据库,并升级到最新版本。这可以让你保持一个完整记录所有数据库变化原子与一个新的版本更新,因此可以生产。
该项目被编译成一个库而不是应用程序。库,可直接运行。NET环境关联。NET工具InstallUtil.exe,或纳入一个更大的应用程序。在运行。NET工具,意味着你可以执行你的数据库的更改,而无需离开。NET环境发展。纳入一个更大的应用程序通常是指一个自定义安装应用程序,但它可以是任何真正的应用程序。
当您模式的转变,并重新生成代码,创建更新脚本,将改变以前的数据库格式到新的数据库格式。您也可以添加自定义的脚本提供版本更新从版本X X版本1时,将只能运行SQL文件。可以添加自定义脚本和计划运行之前或之后更新。可以被添加到在模型中定义的静态数据,静态数据的自定义脚本。您可以添加任意的脚本库,它会被执行。这提供了很大的灵活性,您的部署过程。
重要的是要注意,所有生成的存储过程以及编译到这个库。如果您愿意,您可以添加自定义存储过程,视图等。您可以真正把它当作你的数据库升级路径,这个库的。由于所有的脚本嵌入到库,它可能变得非常大。为了解决这个问题,图书馆本身可以读取ZIP文件。只需创建一个ZIP文件与任何SQL文件,他们将被执行。这是一个不错的功能,对于那些有非常大的邮政编码一样的静态脚本文件,公司目录等,有没有什么特别的做。就像任何其他的SQL文件,并在同一文件夹级别的所有文件将被按字母顺序执行,只要嵌入一个ZIP文件。 高级地图绘制概念
生成的对象如数据类型,可空类型,枚举类型和错误检查他们的概念。根据模型中的一个对象的字段的设置,生成的对象将与每个字段关联的某些属性。当然,一个字段的数据类型是用来创建一个相应的。NET生成的对象类型。但是有更先进的功能以及。标记为可为空字段,生成一个可空的。NET类型。你可以看一下所有非字符串字段和自。NET类型或者允许或不知道,如果允许一个空值。一个字符串是引用类型,所以你不能确定其数据类型属性。
强大的错误检查是不容许客户端代码来分配值将突破数据库,尽可能实施。如果一个空值传递给一个非空的领域,将引发错误。所有对象都一样的长度,为空,类型,您可以使用这些属性来限制用户界面的数据输入到有效数据的元数据描述符。也有共同的业务对象的功能,让您设置或检索数据的一种常用方法,基于对接口和实地枚举。该框架的共同的基本功能,允许应用程序的建设被写入不属于域的具体。换句话说,你可以编写应用程序,可以采取任何产生的任何域模型为基础的API和插件在用户操纵。
枚举类型映射到不变的(或很少改变)数据的静态类型。用户类型表是一个很好的例子。您可能有一个用户类型的数量,但他们几乎从未改变。相反的分配"魔numbersquot;这些值,干脆让发电机为您处理。从那里,你可以在你的代码分配一个枚举,而不是数字。你的代码更具可读性和开发人员可以立即判断的价值意味着什么。接口和基类
生成的所有对象实现一个或多个接口或抽象基类。这允许的用途非常广泛的应用创造。所有生成的映射对象实施了大量的接口,一些基于对象是否是只读或可持久化的或其他允许这样的行动。参加基对象的基础上,在运行时通过英寸的对象类型的用户交互,您可以构建应用程序,你可以获取和设置对象的字段,不知道到底是什么类型的对象。审计领域的接口作为搜索对象和主键访问。
业务对象有两种类型,只读和可持久化。您可以定义为只读的对象,所以他们可以选择,但不保存。这是在类型表和方便还基地对象表。后者是挺有意思的,你可以定义一个表,它本身没有任何意义,而且是一个具体的对象的基类。这样的一个例子是一个抽象的人,是为客户和员工的基础。在您的业务规则,只有客户和员工的通用的人可能没有这样的事情。在这种情况下,使每个人的实体的父表和只读会使人实体。代码,开发人员只能创建客户和员工但没有人。
注意在上面的图,接口模式是相当稳健。不仅从人,但也ICustomer这反过来又继承从IPerson客户继承。所有的业务对象审核。持久化的对象是来自功能少,只读,对象和接口。创建用户界面和业务逻辑时,该模型公开了许多的可能性。{S0}
继承
发生器是没有妨碍的数据库对象类映射到一个具体的。该模型支持对象的继承。您可以定义一个基本类型和继承的任何对象的数量。后端数据库同步是在后台处理。围绕这个概念没有任何特殊的编程。唯一的要求是,派生类中有相同的主键,基数,名称和数据类型。当您选择继承的对象,你看像一个真正的继承对象的所有领域。有没有办法告诉大家,某些领域是从数据库中的基表派生。所有复杂的连接和字段映射下覆盖处理,你从来没有担心从哪个表的哪个字段。
在上面的例子,相关的类图将遵循。请注意,Person实体是从IBusinessObject派生。这是一个接口,没有定义保存功能。客户和员工的子类都来自人,但也实现了该接口IPersistableBusinessObject。此接口公开一种坚持的方法。{S2}回调和通知
生成的对象遵循观察者模式中,你可以注册事件通知。每个对象都有一个全球性的的事件引发之前和之后的字段更改。还有为每个领域的事件,使您可以捕捉为一个单一的领域消息。编译时检查
由于生成的框架为蓝本,你强类型的对象。这可以让你有编译时错误,而不是运行时错误。当一个对象的字段需要以任何方式改变,它的数据类型,名称,为空,等,简单地改变模型和重新生成。当您尝试编译您的应用程序,您将获得由编译器发现的错误。这是比访问字段不能由编译器检查一个字符串比较好。扩展对象
生成的所有对象都是局部类。有一个shell类生成一次并不会被覆盖和quot; generatedquot;类,生成的模型和控制,将始终被覆盖。这允许您添加自定义代码壳类,它显示为一个完全集成的组件对象。审计表
很多时候是要知道在所有时间点的所有数据库中的行的状态。财务审计是一个使用此功能。它可用于数据库管理员(或开发),以确定在任何表的任何行任何值的变化。任何人有此功能的需要,是相当不平凡的实际构建,这是一个相当有用的功能。这是不是除非审计制度到位,因为一个普通的数据库只存储一个行的当前状态,而不是过去国家可以检索的信息。
当一个表被标记为允许审计,影子表创建和维护的系统,所有对表的更改。这包括添加,更新和删除。它是设置表的属性和表活动记录没有问题,如何修改表的简单。这甚至包括生成的框架之外进行修改。寻呼
任何数据库访问技术的一个重要特点是通过大型数据集的能力的页面。不仅发生器允许你这样做,但它允许创建了一个为所有对象类型的强类型的分页对象。这允许你定义一个非常精确的方式如何页面,通过数据。例如,如果你是某一特定领域排序后从模型中删除这一领域,将产生一个编译时错误,因为一切是强类型。排序是非常重要分页时,以来下一页返回的对象必须是确定性的。这就是说,您可以通过任意数量的字段顺序与一个实体的分页对象。选择自定义字段
您可以定义一些领域模型中的搜索。这将确保该字段在数据库中的索引,并建立相应的字段名称的方法,选择父集合。这使得基于一个字段搜索速度极快,因为该字段是索引和搜索机制是一个存储过程。后面更完整的描述。静态数据
您可以实际添加静态数据模型初始化表中的数据。如果你有一个类型表,你可能会想,以确保某些数据表中创建一个数据库时。有一个图形用户界面,允许您设置一个特定的值表中的每个领域。选择命令
您可以创建一个空的子域,并定义选择在批处理执行的命令。在批量加载,例如断开连接的数据集,有可能是业务原因。在这种情况下,有许多预定义的,可以被添加到一个子规则缓存并执行一次SELECT命令。这是与依赖行走后命中的每一次数据所需的数据库对比。有预先定义的SELECT命令选择所有,选择领域,选择关系等,然而,你也可以定义你自己的选择命令,并使用它们交替。
选择命令实际上是依赖行走过程中使用,但可以单独使用加载开发商指定的对象集。有预定义的选择所有主键和外键的方法,以及作为搜索的栏目。所有选择的命令产生局部类和可扩展自定义的SELECT命令。这样的一个例子是一个情况下,你想加载一些非关键领域的基础上的对象。您可以创建一个选择的命令调用一个自定义的存储过程,然后将它添加到选择队列如产生任何其他的选择命令。当然,你可以使用LINQ的功能如下所述任意领域的选择,但这些不能排队,并运行在一个单一的交易。LINQ查询
每个集合RunSelect方法被覆盖多次。查询数据的方式之一是通过在LINQ查询。此功能提供了最大的灵活性,因为您可以执行复杂的查询,只是不开箱的可能,生成的方法。您也可以执行复杂的查询,基于其他表(或对象)的关系。例如,可以定义WHERE条件的基础上表中的字段,一个父表字段,相关表中的字段,相关的表中的父表的字段等所有这一切都执行相同的查询。作为一个提供方便,有没有需要知道实体的继承层次结构,因为你与对象交互,如果它们包含其所有领域以及作为父对象的领域。这使您可以使用一个对象,而不必知道它有5层继承下。
另一个事实值得一提的是,你永远需要联接表。所有的关系都是在模型中定义,所以你可以描述通过引用表,但从来没有定义连接标准的条件。使得你的代码更容易阅读,并确保开发人员不必记住数据库的结构,才能写出正确加入。这是一个大胜利代码的可读性和一致性。开发人员可以不参加生产太多(或太少),结果不正确的字段。这种情况往往会导致意想不到的后果,在这数据看起来是正确的,但实际上是在错误的领域加入。该模型建筑师,确保所有开发人员都以正确的方式访问数据。搜索
有许多方法来搜索。首先,你可以搜索一个预定义的搜索对象。是为每个实体类型生成一个强类型的搜索对象。它允许您定义任何对象的字段搜索基于一个quot; / ORquot;连接器。
你也可以通过使用实体的分页对象的结果页面。这允许你定义一个订货,一次装入一个页面。{C}
现在使用LINQ,你可以实际执行的一些广告特别查询,同时仍然使用强类型的对象。

CustomerCollection customerCollection =

	CustomerCollection.RunSelect(x=>x.BaseName == "SomeValue");


上面的代码返回相同的结果作为使用搜索对象,但现在你可以编写任意复杂的查询,甚至使用隐式连接。
CustomerCollection customerCollection =

	CustomerCollection.RunSelect(x => x.BaseName == "SomeValue" &&

		x.UserType.Name == "MyType");

请注意,上面复杂的LINQ查询实际上是连接三个表。一位顾客是来自人,人有一个有关用户等级和积分。亲子关系在此查询是透明的。它看起来像客户有关联的用户等级和积分的对象,它通过其从Person继承。另外还要注意有没有加入运营商在此查询。没有必要定义的关系,因为他们已经在模型中描述的。
您不仅可以查询基于隐式连接下的继承链相关的实体和横向,但你也可以在多个关系的查询与不同的基数。在下面的代码,客户有一个包一个一对多的关系。你没有注意到它,因为查询看起来完全继承链向下看时,或在关系图横向相同。有没有奇点或多个标识符。
CustomerCollection customerCollection =

	CustomerCollection.RunSelect(x => x.BaseName == "SomeValue" &&

		x.Package.Name == "Pack1");

没有理由知道关系的基数。你只是想寻找客户,有一些字段值相关的包装对象。这是同样的问题,我们要求以上时,我们希望找到一个相关的用户类型的对象的客户,即使客户只能有一个用户类型。这是数据库模型是如何从代码中抽象的另一个方面。
在模型中,你可以定义字段上搜索在运行时。这有助于在发展,因为有很多次,当您正在寻找对象的同一领域的基础上。当一个字段标记为搜索模型,数据库创建索引和实体的相关集合类生成一个自定义的静态搜索方法。这使您可以搜索一组对象一行代码。
CustomerCollection customerCollection =

	CustomerCollection.SelectByBaseName("SomeValue");

这当然是非常有用的,但如果有很多对象,您可能需要通过他们以及。您可以使用客户寻呼对象,要做到这一点。
CustomerPaging paging =

    new CustomerPaging(1, 10, Customer.FieldNameConstants.PersonId, true);



CustomerCollection customerCollection =

	CustomerCollection.SelectByBaseName("SomeValue", paging, "");
依赖散步和延迟加载
生成的框架的一个非常有用的功能是能够加载的对象和quot; walkquot的关系。有没有理由来定义你需要什么对象前面。只需加载一个对象,并开始要求及其相关对象。这在父母与子女的关系的两个方向(的确,即使自引用关系)。
//Load all Customers

CustomerCollection customerCollection = CustomerCollection.RunSelect();



//Get the first Customer

Customer customer = customerCollection[0];



//Write out the UserType

System.Diagnostics.Debug.WriteLine(customer.UserTypeItem.Name);



//How many Packages does this Customer have?

System.Diagnostics.Debug.WriteLine(customer.PackageList.Count);



//The Customer's first Package's Customer (pointer back same customer)

System.Diagnostics.Debug.WriteLine(customer.PackageList[0].CustomerItem.BaseName);

在上面的例子,你可以步行的客户关系的一个用户类型的对象。一位顾客拥有很多包,所以,是PackageList不是PackageItem属性。然后,您可以从拉包列表的第一个项目,并找到一个客户,这当然是你开始使用相同的客户。的关系可以走到上下的关系图。
有趣的是,要注意所有的对象都加载到相同的子域容器。您可以更改任何在该子对象,当您漫步在层次结构,并保存与调用坚持的方法,是在一个事务中对数据库执行。所有对象将被更新一起或一起失败。聚合
另一个方便的功能是提供了强类型的聚合方法。而不是选择一组数据,并进行聚合操作,你可以调用一行代码的聚合函数之一。有最小值,最大值,计数,求和,平均,和独特的功能。它们都是强类型的被查询的字段的数据类型。换句话说,如果你是最大的成本(十进制)字段查询,结果是返回一个对象不是一个小数。 "WHE​​RE子句可以为复杂,因为你想在模型中定义的关系。该方法可以在其中定义的WHERE子句不预定义的。它是完全免费的形式的基于模型。
下面的代码将返回最大值的quot; basenamequot;对所有客户与quot领域; personidquot;小于100。
string name = CustomerCollection.GetMax(x => x.BaseName, x => x.PersonId < 100);

int customerId = CustomerCollection.GetMax(x => x.CustomerId);

还有一个UpdateData聚合方法,将设置一个字段中的一个或多个数据库中的行匹配WHERE条件。这是一个方便的方法,使您可以设置许多数据库中的行,而无需实际加载的行,将它们设置,并将其保存回数据库。您可以在一行代码更新所有匹配的行。
CustomerCollection.UpdateData

	(x => x.BaseName, x => x.BaseName == "Name1", "Name2");

上面的代码更改所有的客户一个quot; basenamequot;领域quot价值; Name1quot; quot新的价值; Name2quot;。此功能也强类型。你的新的价值不能quot; objectquot;,但必须是一个字符串,因为该领域是作为一个字符串定义。这确保了可靠的代码。
还有一个批量删除的方法。上述使用几乎相同的语法,你可以调用DeleteData方法与表达删除所有匹配的记录。此功能允许你选择数据到客户端的情况下,批量删除。
通过LINQ查询的能力实际上是更不仅仅是实施强类型的数据访问模型为基础的有用。实际上,它允许您定义复杂的查询,并在多个地方使用它们。在下面的例子,是一个复杂的访问和更新数据的条款。两次定义的条件,而是我已经定义了一次,并把它用在两个汇总报表。
//Build the "where" statement for later use

Expression<Func<MessageQuery, bool>> where = x =>

	x.RecipientUserId == physician.UserId &&

	x.ViewedDate == null &&

	x.SenderUserId != null &&

	x.IsDeleted == false &&

	x.NotificationSent == null &&

	x.CreatedDate > threshold;



//Use the where statement to get the count

int count = MessageCollection.GetCount(where);

if (count > 0)

{

	//Do something...



	//Update the notification date to now with where statement

	MessageCollection.UpdateData(x =>

		x.NotificationDate, where, DateTime.Now);

}
组件
有时候,你不想选择一个数据库中的一行所有领域。一个行可能包含图片或其他一些大的数据,你不希望一个BLOB字段。为了减少加载时间和内存占用,您可以使用表格组件。这些都映射到一个表中指定的字段的对象。从本质上讲,这是一个字段为表的一个子集。这些全面业务的DAL可以加载和保存,但不创建对象。所以,你可以加载,修改,并坚持对数据库进行更改。更新
无数这样做的方法之一选择您的数据后,你很可能会添加,修改,或删除的对象,并希望这些变化要坚持以存储。幸运的是,绝大多数是生成的基础设施,要做到这一点。如上所述,所有的对象都包含在一个子域。你可以有任意数量随时加载的子站点,但是他们没有彼此的知识。您可以从一个或多个集合到一个子中的一个或多个对象。更改后,只需拨打坚持一个对象的方法,收集,或子坚持的变化。当调用坚持一个单一的对象,该对象(虽然不一定是一个数据库行)方法将被保存。其实这个动作可能会映射到许多物理数据库中的行,因为实体可以被继承,从而映射到多个数据库表。当调用集合或子的坚持,整个子域是坚持。后者的行动是必要的参照完整性。甚至当你不显式创建的所有对象都包含在一个子。
上面的代码检索一个客户主键,修改它,并将它保存。客户对象有一个父集合,又是在一个子位于。您可以动态添加一个子域集合并开始执行这些新的集合操作。在作出任何修改之后,你终于可以保存在一个SQL事务的一个调用所有的变化。整个修改图将成功或失败。
//Get a customer

Customer customer = Customer.SelectUsingPK(1);

customer.BaseName = "NewName";

customer.Persist();



//Add the package collection to the subdomain

PackageCollection packageCollection =

	 (PackageCollection)customer.ParentCollection.

	SubDomain[Acme.TestProj.Business.Collections.PackageCollection];



//Add a new package to the collection

Package package = packageCollection.NewItem();

package.CustomerItem = customer;

package.Name = "MyNewPackage";

packageCollection.AddItem(package);



//Save the Customer and Packages in one transaction

packageCollection.Persist();

在上面的代码,最终坚持节约整个的子域名。不要紧,如果你调用一个集合的persist方法或坚持其容器的子域的方法,结果是一样的。还要注意,所有行动都是强类型。我们没有添加指定的字符串标识符PackageCollection。如果您更改了模型包裹对象名称的包装对象,上面的代码将无法编译。马上你就会知道,这必须予以纠​​正。这种方法是在形成鲜明对比的设计,指定一个名称在引号中的编译器不能检查。事务和并发
所有的选择和更新是原子内的SQL Server事务。当你加载一个对象,对象,或多个集合的集合,这些项目将存在里面的一个子域。这是一个容器,它保存了所有相关信息。你可以有任意数量加载的子域。他们不会相互干扰,并没有彼此的知识。每个对象内部存在一个强类型的父集合对象。所有的集合中的对象存在一个子容器内。这是隐含的。即使当你加载一个对象,它已经有一个父集合andnbsp;父子域。
这是当对象是坚持发挥。当坚持一个集合的方法被调用时,它的整个子域是坚持一个SQL事务。查询计划
生成的代码结构工程以及与SQL缓存。生成的代码在后台使用了两个不同的查询方法。第一种方法是对生成的存储过程的外观。这种方法可以产生极快的结果,因为在SQL Server的查询计划被缓存。共[2 - N]调用存储过程执行一样快,因为SQL可能可以执行的行动。
第二种方法是一个参数化查询。采用这种方法随时对API写一个LINQ语句。在后台,参数化SQL语句生成。这已作为存储过程相同的好处。如果你再次运行相同的LINQ语句,查询计划是由SQL Server高速缓存。需要说明的是,因为LINQ是更自由的形式,你可以创建一个查询的种类繁多。此属性执行更好地在现实世界的应用比在理论上,由于应用不正常问题数以千计的不同的查询,但问题具有不同的参数相同的查询。标准
生成器创建的代码的基础上一天的标准。实体对象是基于接口和基类的层次结构。每个对象都可以描述自己喜欢的类型,规模,友好的名称,外立面等元数据,生成框架实现了行业标准软件模式,以及。所有的业务对象实现Observer模式为现场的通知。活动记录模式是用于与数据库中的主界面。这允许快速和非常灵活的查询技术。对于更多断开的要求,DTO的层实现Repository模式。这种分离从开发人员的数据库访问和允许对象通过网络发送。访问者模式是所有业务集合,让抽象的迭代处理集合对象。 Composite模式是用来定义实体关系。依赖步行是一个关系层次结构,需要开发的一部分,没有特殊的编码。所有实体,有自己的孩子和家长的复合对象。这也有助于在加入与不可见的加入条款或类似的SQL语句的对象。解释器模式实现数据库对象的映射。NET的实体对象。所有的实体和领域,可以有一个门面,掩盖了底层的数据库字段。请记住,一个实体可以映射到多个数据库表和关系。所有这些编码标准是隐含在生成的代码,并从模型中派生。没有特殊的建筑知识是必要的的,使用这些概念。摘要
ORM生成器添加了许多功能项目。该模型允许您控制框架设计的所有方面。所有对象都有明确的类型,有没有哪些对象正在处理的混乱。所有操作,如添加,删除,搜索,分页,更新等是强类型的。一个最重要的功能是编译时错误,如果在一个二进制不兼容的方式模式的转变,将不运行时错误。这是工具的最重要的特点之一。如果对象类型,在模型中添加,更改或删除,是提出一个编译时错误和你的代码(生成和手写)不会建立。可以发现的问题立即没有错误走出去生产。
生成的模型也设计的编码效率。有众多的方法重载,所以你可以加载,保存,并用几行代码传输数据。历史2009年10月4日:初始版本










回答