第一部分:开发新模块 - DNN6
如果你还不知道DotNetNuke是什么的话,请访问 www.dotnetnuke.com
如果你还不知道如何在本地安装DNN 6, 请猛戳 http://codeciel.blogspot.fr/2012/03/how-to-install-dotnetnuke-6-on-local.html
如果你想要知道如何开发一个你自己的DNN6模块,那么这篇文章就是你需要的。
- 步骤1:通过DNN6 Host创建desktop module和module definition
所以,现在你只要按照下面的步骤就可以创建一个属于你的DNN模块 :
- 用host账户登入你的DNN6网站
- 点击Host页面,再进入Extensions页面
- 单击Manage按钮, 选择Create New Module,你将会看到(如Figure 1所示):
提示: 如果你找不到Manage按钮,请确认你的页面模式(通常在右上角可以看见)是Edit而不是View或Layout。
Figure 1 : 创建模块
- 填好这些文本框后。(最后把"Add Test Page ?"打上勾,以简化步骤)- 单击“Create Module”, 然后你就可以看见新的模块已经出现在了“TestEFCodeFirstPage”页面上(如Figure 2 所示)了
Figure 2 : 新页面里包含了新模块
- 步骤2:把新模块与VS项目联系起来
提示:值得注意的事,项目的名字必须与module的名字相同,即“EFCodeFirst”,开始的时候你可以把这个项目保存到任何位置,因为一旦完成创建之后,我们会把这个文件夹移动到<网站根目录>/DesktopModules里,合并这俩个文件夹。
Figure 3 : 创建新vs2010项目
- 再次用VS2010打开“EFCodeFirst.csproj”. 因为我们还需要配置这个项目,来让它可以顺利的在DNN6下编译和运行。- 点击项目属性,然后进入到Compiler页面,修改输出路径为<网站根目录>\bin\
- 如果你Site的运行环境是.net framework version 2.0.50727.5448的话,请在IIS里修改Site的application pool为ASP.NET V4.0。因为EF Code First是需要.net 4.0的。
- 添加Dotnetnuke.dll引用,它可以在<网站根目录>\bin\下找到。需要注意的是在属性里将copy local设置为false。
提示:上面这种添加Dotnetnuke.dll引用的方法不是企业开发常用的,或者说是应该避免的才比较正确。因为Dotnetnuke不断在更新,为了保证团队开发时,Dotnetnuke.dll引用都是同一个版本,我们通常会固定一个稳定的版本来开发。具体操作是:存放指定版本Dotnetnuke.dll的文件夹是共享的,所有的dnn引用都是指向这个文件夹的。- 重命名web.config文件为web.config.old,因为在网站的根目录已经有了一个web.config。
- 删除EFView.ascx文件
- 添加一个新文件,文件类型是Web User Control,还是命名为“EFView.ascx ”,以便DNN能识别。
- 打开文件EFView.ascx, 我们随便写点东西进去,比如 : “This is my first dnn6 module”
- 打开文件EFView.ascx.cs,将它的基类换成PortalModuleBase,保存并编译这个项目
- 刷新页面http://dnn614/TestEFCodeFirstPage.aspx,你将会看到如Figure 4所示 :
Figure 4 : 测试页面和行模块
第二部分 : DNN模块里使用EF Code First
这部分是基于这篇文章: Introduction to Entity Framework Code First
- 步骤 3* : Entity Framework 简介
EF在4.0的时候只提供俩种与实体交互的方法,即数据库优先和模型优先。前一种情况下,你在开发你的应用前开始设计数据库。然后你可以用VS自带的实体数据模型设计工具来设计一个虚拟模型,操作很简单:直接从数据库把表拖拽到设计器中(如Figure 5所示)。后一种情况下,我们先用实体数据模型设计工具来手工设计模型(如Figure 6所示),然后指定数据库的连接。但不管是前面哪种情况,你都要使用实体数据模型设计器来生成你的数据模型对象。
Figure 5 : 数据库优先
Figure 6 : 模型优先
EF在4.1中引入一种新的模式来生成模型对象 : 代码优先(Code First)。在代码优先这种方式里,你不会遇到任何设计器。先全部用.NET Framework来搭建对象类,然后用一些特定属性和相关技术来生成EF数据模型。(如Figure 7一样)
Figure 7 : 代码优先
Figure 8 : EF与实体交互的方式
- 步骤 3 : 创建模型
提示: EFCodeFirstLib项目的文件夹应该放在<网站根文件夹>/DesktopModules/, 并且其编译路径应该是<网站根文件夹>/bin/.
public class BlogPost { public Guid Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime PublishDate { get; set; } public virtual Category Category { get; set; } } public class Category { public Guid Id { get; set; } public string Name { get; set; } public virtual ICollection<BlogPost> BlogPosts { get; set; } }
在BlogPost类中,定义了五个属性: Id, Title, Content, PublishDate 和 Category。注意里面的Category是外键。Category类有三个属性:Id, Name 和 BlogPosts。其中的BlogPosts 是一个属性集合,因为可以有很多个博客帖子属于同一个category。需要记住的是,默认情况下,表示主键的属性类型应该是int或Guid。当然,你可以用一些attributes定制主键。我们将在后面讨论。
- 步骤4 : 创建Data Context
public partial class BlogContext : DbContext { public BlogContext():base("BlogDb") { } public DbSet<BlogPost> BlogPosts { get; set; } public DbSet<Category> Categories { get; set; } }
BlogContext类定义了俩个公共属性,即BlogPosts和Categories。这些属性的类型是DbSet。DbSet类代表了一个实体集(从数据库角度,就是一个数据库的表),可以执行CRUD(创建,读取,更新,删除)操作
- 步骤5 : 测试数据库的生成(可选)
首先在EFCodeFirst项目的“EFView.ascx”中添加一个按钮(button),并且生成相应的按钮点击事件方法。加入我们刚刚创建的EFCodeFirstLib项目的引用。
Figure 9 : 测试页面
然后在按钮点击事件方法中写入以下代码:
using (var db = new BlogContext()) { Guid id = Guid.NewGuid(); var cat = new Category { Id = id, Name = "ASP.NET" }; var post = new BlogPost { Title="Title1", Content="Hello World!", PublishDate=new DateTime(2011,1,1), Category=cat}; db.Categories.Add(cat); db.BlogPosts.Add(post); int i = db.SaveChanges(); }
现在我们编译这俩个项目,在浏览器中打开http://dnn614/TestEFCodeFirstPage.aspx. 点击页面中的按钮。 因为我们是第一次运行并点击按钮,EF将会在SQL Express里创建新的数据库和表。库名是BlogDb,因为我们在DataContext的构造里已经指出了;俩个表名分别是BlogPosts和Categories。
Figure 11: SQLExpress里创建的数据库和表
- 步骤6 : 每次运行(点击按钮)时重新创建数据库
提示:你也可以继承DropCreateDatabaseIfModelChanges类,它只会在Model改变的时候,重新创建数据库。
public class BlogContextInitializer : DropCreateDatabaseAlways<BlogContext> { protected override void Seed(BlogContext context) { Category cat1 = new Category { Id=Guid.NewGuid(), Name=".NET Framework" }; Category cat2 = new Category { Id = Guid.NewGuid(), Name = "SQL Server" }; Category cat3 = new Category { Id = Guid.NewGuid(), Name = "jQuery" }; context.Categories.Add(cat1); context.Categories.Add(cat2); context.Categories.Add(cat3); context.SaveChanges(); } }
protected void Button1_Click(object sender, EventArgs e) { Database.SetInitializer<BlogContext>(new BlogContextInitializer()); ... ... }
- 步骤7 : 在Code First里使用已有的数据库
<connectionStrings> <add name="SiteSqlServer" connectionString="Data Source=(local)\LEGAL;Initial Catalog=DNN614;User ID=login614;Password=xxx" providerName="System.Data.SqlClient" /> <add name="BlogDb" connectionString="Data Source=(local)\LEGAL;Initial Catalog=DNN614_BlogDb;User ID=lgfr;Password=xxx" providerName="System.Data.SqlClient"/> </connectionStrings>
Figure 12 : 指明已有的数据库
如果你在DataContext没有指明,那么那个数据库连接字符串的名字就必须和DataContext类名一样(“BlogContext”)。
为了让大家更清楚Code First选择数据库连接字符串的流程,我们用这个例子再解释一遍 :
- 情况一:在DataContext中(BlogContext)指明了名字“BlogDb”
如果有,EF就会使用这个。如果没有,EF就会在本地的SQL Express中创建一个名为“BlogDb”的新数据库。
- 情况二:没有在DataContext中(BlogContext)指明
如果找到,EF就是使用;否则EF就会在SQL Express里创建一个名为“EFCodeFirstLib.BlogContext”的新数据库。其中EFCodeFirstLib是BlogContext的命名空间。
- 步骤8 : 使用Data Annotations来标明数据表和键的信息
[Table("BlogPosts")] public class BlogPost { [Key] public Guid Id { get; set; } public string Title { get; set; } public string Content { get; set; } public DateTime PublishDate { get; set; } [ForeignKey("Category")] public Guid CategoryId { get; set; } public virtual Category Category { get; set; } } [Table("Categories")] public class Category { [Key] public Guid Id { get; set; } public string Name { get; set; } public virtual ICollection<BlogPost> BlogPosts { get; set; } }
- 总结 :
Code First相对与其他两种方式来说,有很大的灵活性。但我觉得在DNN中不太适合使用,因为我不是特别能接受一个DNN网站同时有俩个数据库,维护起立不方便。所以,在现实项目中,我经常使用的方式是Database First。
最后友情提供一下本例中的DNN模块安装包和源代码:安装包 源代码。Profitez-le et je vous souhaite un très bon weekend !!
Aucun commentaire:
Enregistrer un commentaire