Gain Coding Speed with Nido (FREE) Framework .NET/ C#
Nido 框架与 .Net 4.0 和 Entity Framework 帮助您标准化您的业务逻辑层 (BLL)。
Nido 框架
它是一个免费的开源项目。那么,让我们通过这些面试问题来了解 Nido。
什么是‘Nido’?
Nido 是一个代码框架,一个通用项目,一个架构模式,用 Microsoft .NET/C# 4.5 编写,旨在帮助软件工程师更快地开发他们的系统。这个框架是从我们在开发中心维护的一个通用库中提取出来的,目的是改进我们的工作。我们希望通过‘Nido’实现三个主要目标。
-
速度 – 我们希望您能够更快地编写代码,同时不忽视质量和预算要求。
-
自由 – 我们希望您在想离开时能够离开。当您休假或享受周末时,我们不希望因为紧急情况而给您打电话。我们应该能够与当时在工作场所的任何人处理问题。
-
进步 – 我们帮助您建立一种有条不紊的方法,随着时间的推移改进您的开发中心。
Nido 不是一个一次性的静态框架,它将不断发展并适合您。请通过 CodePlex 关注 Nido 框架。
注意:Nido 框架最适合中小型应用程序开发,目前我们正在使用它开发一个拥有近2000个表的相当大的“ERP”系统。因此,根据我们的经验,该框架足够稳定。
使用“Nido”框架的先决条件
开发版
- 至少 3 - 5 年的开发经验
- 理解“OOP”概念,理解“泛型”概念是必须的
- 实体框架
- 使用现有数据库的 Code-First 技术
系统
- .Net Framework 4.0 或更高版本
- Visual Studio 2010 或更高版本
- 显然需要一些 Windows 操作系统
难道我们不是已经有一些框架了吗?那为什么还要推出一个新的呢?
是的,我们确实看到了许多框架,也有一些不错的 .NET 开发者框架。然而,‘Nido’框架旨在适应其他框架无法适应的特定利基市场。
所以让我解释一下……正如我所说,目前开发的大多数软件系统都是中小型系统。考虑到它们的规模和成本,没有人真正想聘请架构师来为它们做设计。为了支持这个决定,由于这些系统看起来更简单,软件工程师自己也觉得可以单独处理复杂性。然而,当您分析它们的生命周期时,您会发现这些软件也伴随着显著的复杂性。但您不会在生命周期前期或开始时看到它们。随着软件的发展,它会不断扩展。这些可能是以孤立形式出现的微小更改,因此您不会觉得它们是问题。您继续修补核心部分。然而,每次您进行更改时,它们都会引入复杂性,消耗比它们应得的更多一点处理器时间。这会使软件模块变得不稳定,难以管理。
其次,这些微小的修改是由多人完成的,他们以自己的方式进行。因此,代码随着时间的推移变得不一致、不稳定和复杂。这是我们大约 80% 的软件所面临的问题。
‘Nido’旨在解决这些问题,并为从事中小型系统开发的广大开发人员提供一个完整的解决方案。使用‘Nido’,您将以最小的麻烦启动您的系统,并顺利且非常非常快速地完成其生命周期。
现在……请告诉我为什么你总是强调速度,这是否也意味着……其他约束……比如软件解决方案的质量和预算不那么重要?
这是一个好问题……当我说“更快地开发系统”时,这种速度实际上包括了其他约束,例如质量和预算。我们已经借助 Nido 独特的架构做到了这一点……所以我稍后会解释这些。
这有点道理,今天,企业将 IT 作为武器,一种对抗竞争的武器。那么现在,让我再次提问,为什么这些企业希望这种武器更快?您能对此有所启发吗?
长话短说,在当今后现代商业时代,企业的生存就是“持续增长”。要持续增长,您需要扩展业务,还需要改变内部做事的方式,您可能会收购和合并其他业务,并可能努力减少浪费/风险,为客户增加越来越多的价值。但这些会给您的工作行为带来许多变化,并对您使用的相应软件系统产生连锁反应……这些与软件系统相关的变化需要更快地发生。这就是为什么在软件交付方面速度更重要。然而,这并不意味着您可以忽略其他事情,但我想强调速度是关键因素。
‘Nido’,它是一个框架,对吗?总结一下,您会如何向我解释它?我的意思是,它有什么好处?
让我这样开始,任何系统都可以主要分为三个层,从UI层一直到业务逻辑层和数据访问层。现在,您可能会问我,什么是系统?基本上,系统承载着……您业务问题的答案,对吗?
因此,如果您使用‘Nido’来寻找您业务问题的答案,我们将为您提供许多武器。配置完成后,我们将为您提供一个预编码的数据访问层 (DAL),它具有以您能想到的各种方式访问数据的选项。然后它还会为您编码一个相当不错的业务逻辑层。为此,它将使用一种名为‘t4template’的技术。一旦您达到这个阶段,您将拥有许多可用于解决任何业务问题的离散业务功能。所以,下一步,您需要使用这些预编码的功能,通过UI层以有意义的方式连接,以提供所需的业务解决方案。
此外,在这些解决方案中,您会发现一些常见类型的问题,您可以以多种不同方式提供解决方案。例如:
- 处理登录异常,显示用户友好的消息,跟踪错误。
- 跟踪对重要数据项所做的更改,这也被称为审计跟踪
- 验证记录和加密敏感数据以保护其隐私
- 通过以一种标准方式处理复杂问题来控制复杂性
- 设定编码标准模式
所以这些事情对于您做的其他每个系统来说都是常见的,但是使用'Nido'框架,我们引入了一种常见的、标准的方法来解决所有这些问题。
有了这个,我能说‘Nido’框架是一套标准吗?这个说法正确吗??
答案既是“否”也是“是”。“否”的意思是‘Nido’团队开发了很多东西。它们不仅仅是标准,它们是以通用形式编写的代码。因此,一旦您将‘Nido’集成到您的项目中,您就将大部分功能继承到您的项目中。您只需编写几行代码就可以派生出以通用形式开发的大部分功能。
“是”的意思是,您还可以通过遵守某些标准或扩展给定功能来增强某些默认功能。在这方面,我们确实定义了标准,以确保我们都以相同的方式使用'Nido'。
它有什么好处,另外请告诉我……为什么我的公司应该使用‘Nido’?
‘Nido’……将为您带来许多好处。您应该将您的经验和学习从一个系统延续到下一个系统,但如果没有这样一种有条不紊、逻辑化的方法来做到这一点,这个过程效率会很低,但是有了‘Nido’,您将能够以一种更有条理的方式提升您的开发人员,这样随着时间的推移,您花在编码上的时间会越来越少。此外,一致性和统一性也很重要。除此之外,‘Nido’还会减少开发人员的个人依赖。我们作为开发人员,都会对自己编写的代码模块产生依赖。这对我们和公司都不利。我们应该避免这种情况,而'Nido'将帮助您做到这一点。
此外,有了'Nido',您的工作也变得更具可预测性。这主要是因为您在许多系统中重复使用通用库,并且无论您开发何种类型的系统,都以类似的方式进行开发。您可以开始使用'Nido'来体验这一点。这也与软件估算有关,工作量估算是最容易出错的领域之一。这就是为什么公司发现很难从固定报价项目中盈利。然而,通过改进可预测性,使用‘Nido’,您将能够比以前更准确地进行工作量估算。
我的意思是,我并不是说您只能通过‘Nido’获得这些好处,任何其他设计良好的框架都可以为您提供这些好处。但对于 Microsoft .Net 来说,这种性质的框架并不多。所以从这个意义上说,'Nido'是一个独特的解决方案。
框架的设计非常重要,尤其是当我们要将其用于每个其他系统时。那么您能解释一下您的设计决策以及在为‘Nido’设计时面临的挑战吗?
让我先解释一下大局。设想一个智能系统,它可以根据使用情况自动更改和配置自己。例如,当某个屏幕比其他屏幕使用更频繁时,系统会智能地更改导航路径,以便更快地访问这些屏幕;或者当某个特定字段持续被忽略时,系统会智能地响应并重新设计 UI,以隐藏那些未使用的字段。这就是我们使用‘Nido’的目标。
但显然,那是高层目标。但在实际情况中,我们现在正在处理代码的后端部分,在那里我们让您使用‘Nido’自动创建 DAL 和 BLL。我们在此处做出了一些设计决策。
Nido 框架概述,如您所见,Nido 将大大减少您的业务逻辑和数据访问层的大小。
-
在哪里发挥作用?我们试图为‘Nido’确定一个发挥作用的领域。如今开发的大多数系统都是中小型系统。其中大多数在架构上也很脆弱。因此,我们决定专注于这些系统,为它们提供正确的架构组合。所以我们将在中小型系统上发挥作用。
此外,通过‘Nido’,重点是帮助设计后端。这样,我们将帮助您更快地编写后端代码。现在,您节省的那些时间可以/应该投入到 UI 层,使其更具创意和用户友好性。
-
如何发挥作用?因此,第二个设计决策是找到实现这些目标的方法。作为首要原则,我们不想让事情变得复杂。我们专注于简单的设计。因此,我们付出了额外的努力,让开发人员也更容易理解事物。我们知道,我们作为编码人员,经过一段时间后都会忘记最初建立的编码标准和架构。这就是为什么我们建议设立一个独立的管理机构来控制和监控编码。这个框架将成为这个控制机构。在这里,我们强制执行标准、最佳实践、编码模式等。您使用‘Nido’,而我们则每年都在改进框架。如果您认为您也想这样做,那么请加入我们。我们将共同进步,而其他普通开发人员则可以享受自由。
为了使所有事情对我们所有人都更简单,‘Nido’团队决定以泛型类的形式开发许多代码,这样您就不必进行复杂的编码或记住任何东西。此外,大部分代码都是使用 t4tempaltes 自动为您生成的。一旦您开始使用'Nido',您就会意识到使用‘Nido’框架是多么容易。您不会在‘Nido’中看到任何无用的东西,我们对添加到‘Nido’框架中的内容非常小心。
我们使用了一些知名的第三方库,例如:
- EntityFramework
- EntityFramework.Extended
- EntityFramework.BulkInsert-ef
- RefactorThis.GraphDiff
- EntityFramework.MappingAPI
- CompareNETObjects
- Log4Net
如果您想了解一些设计决策的更精确细节,您可以参考我之前写过的另一篇文章,名为 '架构指南:ASP.NET MVC 框架 + N 层 + Entity Framework 及更多内容' 。尽管该架构与我在这里使用的架构并非一一对应,但您可以参考它来理解所有主要设计决策。
如何配置‘Nido’?
最简单的方法是通过 NuGet 的包管理器控制台安装它。请按照以下步骤操作。
-
打开 Visual Studio 2010 或 2012
-
创建一个新的“类库”类型项目
-
将其命名为<您的项目名称>.Bll,拥有此“.Bll”后缀很重要,因为使用‘Nido’框架,我们将创建一个项目,它实际上将 DAL 与 BLL 结合在一起。因此,我们现在创建的项目是您项目的整个后端系统。
-
点击 \视图\‘其他窗口’\‘包管理器 控制台’打开‘包管理器控制台’。
-
在控制台中键入“Install-Package NidoFramework’。点击Enter。现在,等待几分钟,直到‘Nido’框架和相应的库安装完成。
-
重要提示:您需要授予覆盖现有‘App.config’文件的权限。因此,您可以检查‘包管理器控制台’,它应该在那里提示权限。
-
创建数据库以测试项目。如果您已有数据库,则可以忽略此步骤。
-
您可以在此新创建项目的 DB 文件夹中找到一个包含一些示例数据的 SQL 脚本数据库。
-
首先在您的 MS SQL 数据库(最好是 MSSQL 2008 或更高版本)中创建一个名为‘School’的数据库(这只是为了测试运行),然后在该数据库上运行‘Sample_Db_Bak.Sql’中的脚本。
-
这将创建一个包含多个表和数据的数据库。
-
-
“Templates”文件夹中有三个文件(tt文件)。您可以从“Models.tt”、“Handler.tt’和“DbContext.tt’开始,逐一更改每个文件中的连接字符串(是的,我会将其设为公共变量)。查找名为“connectionString”的变量。保存更改后,它应该会自动开始生成相应的文件。但是,如果它没有自动生成,您可以右键单击它们中的每一个并选择“运行自定义工具”以手动触发它。
注意:请确保您的数据库符合文档部分中给出的基本指南。
-
使用Models.tt生成模型类。它们直接映射到您的数据库表。但是,您可以选择通过使用 [NotMapped] 属性(您可以在那些自动生成的模型中看到一些示例属性)来向这些类添加额外的字段。创建类后,将它们复制到“Models”文件夹中。
-
使用Handler.tt生成处理程序类。它们用于与数据库交互。您可以将生成的类复制到“Handlers”文件夹。请参阅文档以了解它们的用法。
-
使用DbContext.tt生成 DB 类,然后将其复制到‘DB’文件夹。这是数据库上下文类的表示。
-
-
创建您的前端解决方案(Web、桌面、Web 服务、Win 服务等),并添加对上述 BLL 项目的项目引用以使用‘Nido’框架。
-
有关更多详细信息,您可以阅读文档并查看示例项目。此外,您还可以观看我们的使用指南视频。
我如何在‘Nido’上编写代码,您能给我一些基本提示吗?
现在,一旦您配置了‘Nido’,您的后端就准备好了,接下来您需要为项目创建一个前端。将新的 Web 应用程序、桌面应用程序或任何其他项目添加到您的解决方案中。添加对您刚刚创建的业务逻辑层 (BLL) 项目的引用。此外,您还需要添加对‘Nido’中使用的所有其他第三方 dll 的引用。最后一步,您可以将连接字符串添加到 web.config 或 app.config 文件中,如下所示。这就是‘Nido’知道在哪里找到您的数据库的方式。
重要提示:‘Nido’框架已在 MS SQL Server 2008 上进行测试,但理论上它应该适用于所有 MS SQL 版本以及 Entity Framework 6.0 支持的任何其他数据库。为了将‘Nido’框架与数据库进行配置,您需要在配置文件中包含以下条目。
<connectionStrings>
<add name="name of the DBContext class"
connectionString="data source=<db server>;
initial catalog=<database>;user id=<user name>;password=<pass word>;
multipleactiveresultsets=True; timeout=500" providerName="System.Data.SqlClient" />
</connectionStrings>
重要提示:这里的“DBContext 类的名称”是您在 BLL 项目的 DB 文件夹中找到的 DB Context 的名称。这与您使用 Entity Framework Code First 技术所做的配置完全相同。
从数据库加载数据
如果您想从'Student'表中加载数据,您需要使用‘StundentHandler’类(这些类是自动为您创建的)。让我向您展示如何从'Student'表中加载数据。
protected void LoadData()
{
StudentHandler handlerStudent = new StudentHandler();
GenericResponse<IEnumerable<Student>> response = handlerStudent.GetAllGeneric();
if (response.Successful)
{
this.GridView1.DataSource = response.Result.ToList();
this.GridView1.DataBind();
}
else
this.DisplayError(response.Messages[0]);
}
如果您想包含多个表并一起加载它们,您可以在调用加载数据之前在‘handlerStudent’中指定。
handlerStudent
.Include("HomeAddress")
.GetAllGeneric();
这将加载'Student'记录以及每个学生的相关‘HomeAddress’。此学生处理程序类将支持以所有可能的方式加载学生记录。让我向您展示一种更复杂的方式。下面的代码将加载包含‘HomeAddress’和‘StudentCourses’以及其‘Courses’的学生(这些功能是从 EntityFramework 6.0 中提取的)。此外,它还将进行条件加载,仅加载‘IsActive’字段值为‘true’的学生。
handlerStudent
.Include("StudentCourses.Course")
.Include("HomeAddress)
.GetAllGeneric(x => x.IsActive == true);
这些加载旨在将数据库访问和往返次数降至最低,因此建议您在过滤出您实际需要的记录集后,在最后一刻才调用诸如‘ToList’或‘ToArray’之类的方法。如果您提前调用它们,然后尝试进行过滤,那么您最终会加载大量不必要的数据到您的机器内存中。
重要:此返回对象包含有关调用、其状态和遇到的错误的许多详细信息。此外,它还包含一条用户友好的消息,供您在方法调用遇到任何错误时显示给用户。‘Nido’会将所有错误记录到一个异常日志文件中,您可以通过‘web.config’或‘app.config’文件进行配置,并带有一个引用 ID。然后它会返回一条需要显示给用户的消息,其中包含该引用 ID。这样,用户需要报告带有引用 ID 的错误,开发人员可以通过该 ID 在异常日志中直接跟踪相应的错误。异常日志配置详细信息可以通过查阅 log4Net 项目网站获取。无论如何,当您通过包管理器控制台安装‘Nido’时,您将获得一个 App.Config 文件,其中包含 log4net 设置,用于将错误写入 txt 文件。将阈值级别设置为‘Info’以查看所有事务的跟踪。
<!--DEBUG < INFO < WARN < ERROR < FATAL-->
<param name="Threshold" value="INFO"/>
为了您的理解,我将在下面向您展示一个示例信息日志(它会跟踪常规错误日志,但这是当您将阈值设置为“INFO”时)。请注意它捕获的详细信息量。这种类型的日志对于最初的生产发布非常重要,因为您对系统的稳定性不太确定。这将帮助您更容易地跟踪最初的生产错误。但是,随着系统越来越稳定,您可以提高阈值级别以减少日志。
2014-01-02 09:45:37,530 [5] INFO DemoTest.Bll.Handlers.CourseViewHandler - Calling start for GetAllGeneric()
2014-01-02 09:45:37,545 [5] INFO DemoTest.Bll.Handlers.CourseViewHandler - Calling End Successfully for GetAllGeneric()
2014-01-02 09:45:38,103 [5] INFO DemoTest.Bll.Handlers.StudentHandler - Calling start for GetFirstGeneric(x => ((x.Age == 10) AndAlso (x.CanDelete == True)))
2014-01-02 09:45:38,263 [5] INFO DemoTest.Bll.Handlers.StudentHandler - Calling End with erros for GetFirstGeneric(x => ((x.Age == 10) AndAlso (x.CanDelete == True)))
我们目前正在使用“info”日志来跟踪性能问题。我们所做的是,在发布到生产环境后立即启用 info 日志,然后持续监控日志。我们学到的一个教训是,对于复杂的数据检索,最好使用“视图”。此外,在审查了我们的 info 日志后,我们还引入了高度优化的“批量插入”选项。请允许我借此机会特别感谢EntityFramework.BulkInsert团队和 maxlego。
我听说使用'Nido'您可以从缓存中加载数据,这是真的吗?
是的,这是我想强调的另一个重要功能。从数据库加载数据是昂贵的。因此,您可能已经想过为什么我需要反复访问数据库来加载数据。是的,使用'Nido'您可以缓存它们。如果您想缓存数据,那么您需要创建一个缓存策略。请查看下面的代码,我们通过Paul Welter和他的'loresoft'团队开发的'EntityFramdwork.Extended'库提供了此功能。
StudentHandler handlerStudent = new StudentHandler();
// Defined a cache policy and assign a reference tag for this particular cache object
var tasks = handlerStudent.GetAllFromCache(x => x.IsActive == true
, new NidoCachePolicy(300)
, tags: new[] { "ActStudents", "All sActive Students" });
// some update happened to Students, so expire ActStudents tag
NidoCacheManager.Current.Expire("ActStudents");
此功能可用于加载不经常更新的记录。这样您就可以将数据保留在内存中,而无需重复访问数据库。您可以利用获得的处理器能力和网络带宽进行其他重要的数据检索。
但是,也可能存在需要强制框架从数据库加载数据的情况。在这种情况下,您可以调用以下代码使缓存对象过期。
NidoCacheManager.Current.Expire("ActStudents");
将记录更新回数据库
如果您想将学生数据更新回 Student 表,那么您需要使用‘StundentHandler’类。让我向您展示如何做到这一点。这是一种更简单的更新记录的方法。
StudentHandler handlerStudent = new StudentHandler();
GenericResponse<Student> stdRes = handlerStudent
.GetFirstGeneric(x => x.StudentId < 34);
if (stdRes.Successful)
{
stdRes.Result.Age = 1000;
GenericResponse<Student> stdUpRes = handlerStudent
.UpdateGeneric(stdRes.Result);
}
然而,您可能需要进行更复杂的更新,例如,如果您正在更新多个记录,您可能需要单独附加它们,在这种情况下,您可能需要使用附加方法来附加其他相关对象。此功能是使用‘EntityFramework’开发的,因此您在使用 EF 时获得的任何学习都可以在此处使用。
handlerStudent.AttachChild<StudentCourse>(studentObj.studentCourseObj)
.AttachChild<Address>(studentObj.addressObj)
.UpdateGeneric(studentObj);
然而,您可以使用更可预测和稳定的方法进行更复杂的更新,方法如下。
private void UpdateRecord(Student student)
{
// First you update the Stundent
student.Age = 308;
student.Description = "Editted on " + DateTime.Now;
student.Name = string.Empty;
// Assume that you have updating the student that has many StudentCourses associate with it
// Now you are modifying one of such StudentCourse
student.StudentCourses.FirstOrDefault().Course.Period = 308;
student.StudentCourses.FirstOrDefault().Course.Name = "Eddited on " + DateTime.Now;
// Now you decided to remove a given element (or elements)
student.StudentCourses.Remove(student.StudentCourses.FirstOrDefault(x=>x.StudentCourseId == 10));
// You create and add a new course to Student
Course course = new Course();
course.EndDate = DateTime.Now;
course.IsActive = false;
course.IsWeekEnd = true;
course.Name = "Newly added course on " + DateTime.Now;
course.Period = 10;
course.StartDate = DateTime.Now;
StudentCourse stdCourse = new StudentCourse();
stdCourse.StudentId = student.StudentId;
stdCourse.CourseId = course.CourseId;
stdCourse.Course = course;
student.StudentCourses.Add(stdCourse);
StudentHandler stdentHandler = new StudentHandler();
GenericResponse<Student> response = stdentHandler.UpdateGraphGeneric(student
, map => map.OwnedCollection(p => p.StudentCourses
, with => with.OwnedEntity(p => p.Course)));
}
此功能是借助名为‘GraphDiff’的第三方库开发的,该库由 Brent Mckendrick 开发。如果您想了解更多详细信息,可以参考他的博客。您可以在互联网上搜索以了解更多信息。您会惊讶地看到他开发的一些不错的功能,以支持通过实体框架进行复杂的模型更新。
下面给出的更新选项很有趣。它将查找所有 StudentId 大于“0”的学生,并将其姓名更改为“Updated”。这是一种高效的批量更新方式。此功能由 LoreSoft 的‘EntityFramework.Extended’提供。您可以参考他们的网站查看他们提供的所有不错的功能,这样您也可以在‘Nido’中使用它们。
StudentHandler stdentHandler = new StudentHandler();
handlerStudent.UpdateGeneric(t => t.StudentId > 0
, t2 => new Student { Name = "Updated" });
从数据库中删除记录
删除功能相当简单。您可以使用以下任一选项从数据库中删除一条或多条记录。
-
handlerStudent.DeleteGeneric(entityObject);
-
handlerStudent.DeleteGeneric(12); // 通过传递主键
-
handlerStudent.DeleteGeneric(x=>x.StudentId>10); // 通过传递表达式
向数据库添加记录
handlerStudent.AddGeneric(entityObject);
或下面这个。下面的方法是在 EntityFramework.BulkInsert 的帮助下开发的,它是由 maxlego 和他的团队开发的。您可以在相应的 codeplex 网站上查看其性能和其他优势。
handlerStudent.AddBulkGeneric(entityObjectList);
我听说使用'Nido'您可以让开发人员直接在生产环境中测试系统,这是真的吗?
是的。这是非常有用的功能之一。您知道,有时我们开发人员会遇到奇怪的编码问题。其中一些只在生产环境中出现,您必须在生产环境中调试才能重现问题。我们为您提供了一个解决方案,Nido 允许您在生产环境中使用生产数据测试您的系统,但不会更改生产数据。如果这对您很重要,请继续阅读……
假设这是一个 Web 应用程序,您需要做的是在 Visual Studio 中加载源项目,并更改 Web 配置文件以连接到具有下面特殊配置的生产数据库。然后您可以使用生产数据调试系统。它将显示您在会话中进行的更新(并且仅适用于具有该配置文件的您)。这对于跟踪那些只在生产环境中发现的罕见错误非常重要且有用。
为了使其正常工作,您只需将以下配置添加到您的配置文件中。
<add key="EnableTesting" value="true"/>
我有一些敏感数据,需要以加密形式保存在数据库中。您有什么解决方案来使用‘Nido’加密敏感数据吗?
是的,您可以使用 Nido 完成此操作。您只需使用“Encrypted”属性标记模型的相应属性即可。一旦您这样做,记录将在保存时自动加密,并在从数据库检索回以显示在用户界面 (UI) 上时解密。通过此功能,您可以将敏感数据以加密形式保存在数据库中。
public class Student : BaseObject
{
[Encrypted]
public string Name { get; set; }
}
在某些情况下,记录更改非常重要。这对于 ISO 认证也很重要。‘Nido’有这方面的解决方案吗?
跟踪更改或审计跟踪是一个重要的功能。您可能需要跟踪对某些重要记录所做的更改。需要跟踪更改历史记录。在这种情况下,您可以配置‘Nido’为您完成此操作。
这就是您如何做到这一点。在您的 BLL 项目的 Models 文件夹中,由‘Nido’安装创建,有一个名为‘AuditTrails.txt’的文件,该文件中包含启用此功能的指南。请遵循该指南。
完成此操作后,您的系统就可以进行审计跟踪了。现在您需要告诉框架您需要跟踪的字段。为此,您只需如下所示用“Auditable”属性标记字段。
public class Student : BaseObject
{
[Auditable]
public string Name { get; set; }
}
在框架上编码时,有很多建议以充分利用它。那么您对开发人员还有哪些其他建议呢?
是的,我们还有其他一些建议,让我按顺序说明它们……
建议 1
假设您想合并来自多个表的记录。那么您可以使用未映射的字段。
例如,如果您想显示'Student'以及学生地址,那么您可以添加一个字符串作为未映射字段,并加载学生(包括地址),如下所示。
StudentHandler stdentHandler = new StudentHandler();
stdentHandler.Include(student=>student.Address).GetAllGeneric();
Student Model need to following update
Public class Student
{
// Regular fields in the Student Class
[NotMapped]
Public string StudentAddress { get { return Address.ToString(); } }
// I assumed that ToString method will format the address
}
建议 2
如果要进行复杂的数据检索,最好的选择是使用视图,这将提高性能并减少网络流量。因此,为了改进该功能,您可以创建一个新的视图对象并将所有记录加载到该视图中。这样,您就可以将视图加载到新创建的模型对象中,并将其传递给 UI。
从这个意义上讲,您必须手动创建一个模型,该模型映射您在数据库视图中拥有的字段。然后,您还需要像为表对象所做的那样创建一个新的处理程序类。然后,您可以像加载任何其他数据库表一样加载视图。这是一种高效的方式来执行复杂的数据检索。
建议 3
使用存储过程减少网络往返。如果您调用存储过程且不期望返回值,那会很干净。但如果您也期望返回对象,那么您必须创建一个新的模型对象来与从存储过程获取的记录进行匹配。由于它是一个平面对象,您不必像往常一样从‘BaseObject’派生此模型。在同一节点上,定义一个单独的主类来处理所有存储过程调用。现在您可以按如下方式进行存储过程调用……
public GenericResponse<IEnumerable< Return Object >> CustomGetMethod()
{
try
{
myDbContext db = new myDbContext();
IEnumerable<Return Object> s = db.ExecuteStoredProcedure("<you sp name> @param1
, @param2"
, new SqlParameter("@param1", param1 value)
, new SqlParameter("@param2", param2 value);
// return UpdateSuccessResponse(<Updated Address>);
// return DeleteSuccessResponse(<Deleted Address>);
return SelectSuccessResponse(s);
}
catch (Exception e)
{
return HandleException<IEnumerable<Address>>(e);
}
}
建议 4
如果您想轻松使用 Nido,则需要遵守一些数据库指南。
- 为表提供有意义的名称
- 所有表都使用主键。主键应包含表名,后跟后缀“Id”(例如,主键 = TableNameId)。这也适用于复合表。
- 如果您要在下拉框中显示表记录,则“Name”列会派上用场。
- 表的外部键名称也可以使用表名,后跟后缀“Id”
- 它们可以像在 EF 中创建一样创建。
- 尽可能多地使用存储过程,以避免不必要的数据库往返。
总结一下,它还有哪些其他好处?
- 使用 log4net 的异常登录
- 包含操作详情和参数的事务登录
- 审计追踪 - 记录审计追踪,符合 ISO 认证要求
- 特殊测试模式 - 用于在生产环境中测试系统的特殊测试模式,支持生产数据库的内存版本,即您将在不实际更改生产数据的情况下使用生产数据库。
- 批量操作,通过 Entity Framework Extensions 实现批量更新、批量删除功能
- 缓存 Linq 查询结果
其他参考资料
历史
- 2013-12-18:初始版本
- 2014-01-07:添加了如何缓存
- 2014-10-01:根据一些用户评论,完全修改了整篇文章