怎么在ASP.NET WebForm中使用Razor视图引擎

前几天微软发布了一堆新技术,详见ScottGu的博客:

Announcing release of ASP.NET MVC 3, IIS Express, SQL CE 4, Web Farm Framework, Orchard, WebMatrix
http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx

 

让人特别感兴趣的是ASP.NET MVC 3和WebMatrix中的Razor视图引擎,其简洁明了的句法给人以耳目一新的感觉,ScottGu对它做了很多介绍,详见上面链接中有关Razor部分的内容和链接。

但这些介绍基本上是围绕着ASP.NET MVC 3来进行的,在WebForm中是否能够用它来渲染视图呢?可以的,这里做一个简单的示范:

安装ASP.NET MVC 3,在你的web应用中添加对System.Web.WebPages程序集的引用。

在项目中添加一个.cshtml文件(假定你的项目是基于C#的),在这里我生成了一个weibo.cshtml,其中的内容为:

 

欢迎去 @Model.Name 的新浪微博 <a href=”@Model.URL”>@Model.URL</a> 拍砖!

 

所用的Model是一个自定义类:

public class UserInfo
{
    public string Name { get; set; }
    public string URL { get; set; }
}

在你Page的HTML中加一个Panel:

<asp:Panel ID=”pnlContent” runat=”server” />

然后在Page_Load方法中,

var model = new UserInfo { Name = “思归”, URL = “http://t.sina.com.cn/timeflieslikeanarrow” };

var path = System.IO.Path.Combine(Request.ApplicationPath, “weibo.cshtml”);
var type = BuildManager.GetCompiledType(path);

System.Diagnostics.Debug.Assert(type != null);

var script = Activator.CreateInstance(type) as System.Web.WebPages.WebPage;

System.Diagnostics.Debug.Assert(script != null);

var writer = new System.IO.StringWriter();

script.ExecutePageHierarchy(new System.Web.WebPages.WebPageContext(new System.Web.HttpContextWrapper(HttpContext.Current),
                                null, //rendering page
                                model), //model
                          writer);

pnlContent.Controls.Add(new LiteralControl(writer.ToString()));

 

运行该网页,你会看到这样的输出:

 

欢迎去 思归 的新浪微博 http://t.sina.com.cn/timeflieslikeanarrow 拍砖!

 

参考:

WebMatrix and DNN – 5 – Hosting the Razor Engine
http://www.dotnetnuke.com/Resources/Blogs/tabid/825/EntryId/2858/WebMatrix-and-DNN-ndash-5-ndash-Hosting-the-Razor-Engine.aspx

Hosting the Razor Engine for Templating in Non-Web Applications
http://west-wind.com/Weblog/posts/864461.aspx

Razor Templating Engine
http://razorengine.codeplex.com/

发表在 未分类 | 评论关闭

更多WP7开发资源

下面是我陆续在新浪微博上贴出的Windows Phone 7 开发资源:

1. 开发时如何监测WP7应用的内存:Monitoring Memory Usage on Windows Phone 7 (http://sinaurl.cn/hb9YzR )和 Debug Memory Counter for Windows Phone 7 (http://sinaurl.cn/hbQmTc

2. Rob Miles的《Windows Phone Programming in C# 》课程资料(https://www.facultyresourcecenter.com/curriculum/pfv.aspx?ID=8729&Login&Login= ) 【来源】New Windows Phone 7 Curriculum available! (http://sinaurl.cn/hboEwQ

3. 微软Windows Phone开发团队推出Windows Phone Recipes (http://sinaurl.cn/hbjQGC ) 一堆开源项目,提供一些可重用的代码,以帮助WP开发人员,第一个菜谱是Nonlinear Navigation Service

4. Windows Phone 7 Developer Guidance Map v2.0: http://sinaurl.cn/hbaoCr

5. WP7 developer resources slide: http://sinaurl.cn/hbYwhp

6. 用Fiddler在另一台机器上监测WP7的通讯:More Monitoring Web Requests on Windows Phone: http://sinaurl.cn/hbatDE

7. 微软模式和实践开发团队推出《Windows Phone 7 Developer Guide 》:http://sinaurl.cn/hbc4qb 也可在 http://sinaurl.cn/hboZhH 下载,相关代码可在这里下载: http://sinaurl.cn/hboZhB

8. 《Send Push Notifications to Windows Phone 7 from PHP》:http://sinaurl.cn/hbV6YT

9. Silverlight 4 Firestarter培训教程:http://sinaurl.cn/hbccBS 其中第11个是关于WP7的

10. 《开发人员最爱Silverlight 5的十件事》: http://sinaurl.cn/hbZjR7

11. 在调试WP7时,发现Fiddler(http://sinaurl.cn/hMYhv ) 无法拦截web traffic, 最后用了微软的network monitor (http://sinaurl.cn/hbq6DR ), 新的Fiddler beta版本支持了: http://sinaurl.cn/hb7LPx

12. Windows Phone 7设计文档和录像链接: Build beautiful apps with Windows Phone 7 design guidance (http://sinaurl.cn/hbv9kk )

13. Jesse Liberty的《Windows Phone From Scratch 》系列:http://sinaurl.cn/hbU3Tw

14. 现在你可以使用VB.NET来开发Windows Phone 7应用了:Visual Basic for Windows Phone Developer Tools – RTW http://sinaurl.cn/h4s5Zl

15. 《Building a ‘real’ Windows Phone Twitter app Part 7 – Optimizing ProgressBar and First time app start up》(http://sinaurl.cn/hbLsTb

发表在 未分类 | 评论关闭

【翻译】EF 特性 CTP5版: 流畅 API 例子

【原文地址】EF Feature CTP5: Fluent API Samples
【原文发表日期】 6 Dec 2010 9:00 PM

我们刚发布了实体框架特性第五个社区技术预览版 (简称CTP5)。 特性CTP5版包括了我们计划在2011年第一个季度以独立的软件包形式发布的新特性的预览内容,希望得到大家的反馈。特性CTP5版建立在随.NET框架4.0和Visual Studio 2010发布的现有实体框架4(简称EF4)的功能之上,是我们先前CTP版本的更新版。

Code First提供了一个流畅(Fluent)API,可以用来进一步配置一个模型,本贴将提供一系列使用流畅API的简短例程。

注: 流畅 API是个比较高级的概念,本贴假定你对代码优先简介一文中详述的概念有所理解。

模型

在本贴展示的例程会使用下述模型:

public class ProductContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
public DbSet<Tag> Tags { get; set; } public DbSet<Person> People { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<OrderLine> OrderLines { get; set; } public DbSet<OrderLineNote> OrderLineNotes { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) {
// TODO: Use Fluent API Here } } public class Category { public string CategoryCode { get; set; } public string Name { get; set; } public virtual ICollection<Product> Products { get; set; } } public class Product { public int ProductId { get; set; } public string Name { get; set; } public string PrimaryCategoryCode { get; set; } public virtual Category PrimaryCategory { get; set; } public string SecondaryCategoryCode { get; set; } public virtual Category SecondaryCategory { get; set; }



public virtual ICollection<Tag> Tags { get; set; } } public class DiscontinuedProduct : Product { public DateTime DiscontinuedDate { get; set; } }
public class Tag { public string TagId { get; set; }

public virtual ICollection<Product> Products{ get; set; } }
public class
Person { public int PersonId { get; set; } public string Name { get; set; } public Address Address { get; set; } public ICollection<Order> Orders { get; set; } } public class Address { public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } } public class Order { public int OrderId { get; set; } public DateTime OrderDate { get; set; } public ICollection<OrderLine> Lines { get; set; }
public Person Person { get; set; } } public class
OrderLine { public int OrderId { get; set; } public int ProductId { get; set; } public int Quantity { get; set; } public Product Product { get; set; } public ICollection<OrderLineNote> Notes { get; set; } } public class OrderLineNote { public int OrderId { get; set; } public int ProductId { get; set; } public string Note { get; set; } public OrderLine OrderLine { get; set; } }

 

主键

简单的主键:

modelBuilder.Entity<Category>()
    .HasKey(c => c.CategoryCode);

复合主键:

modelBuilder.Entity<OrderLine>()
     .HasKey(l => new { l.OrderId, l.ProductId });

 

属性

将一个在CLR中可为null的属性设成必需的:

modelBuilder.Entity<Product>()
    .Property(p => p.Name)
    .IsRequired();


改变字符串长度:

modelBuilder.Entity<Product>()
    .Property(p => p.Name)
    .HasMaxLength(50);


关闭Identity:

modelBuilder.Entity<Product>()
    .Property(p => p.ProductId)
    .HasDatabaseGenerationOption(DatabaseGenerationOption.None);

忽略一个属性:

modelBuilder.Entity<Person>()
    .Ignore(p => p.Name);

 

类型

指定一个类型为复杂类型:

modelBuilder.ComplexType<Address>();

忽略一个类型:

modelBuilder.Ignore<Person>();

 

关系

标准的一对多:

modelBuilder.Entity<Product>()
    .HasRequired(p => p.PrimaryCategory)
    .WithMany(c => c.Products)
    .HasForeignKey(p => p.PrimaryCategoryCode);


同样的关系也可从另一端配置(其效果与上面的代码相同):

modelBuilder.Entity<Category>()
    .HasMany(c => c.Products)
    .WithRequired(p => p.PrimaryCategory)
    .HasForeignKey(p => p.PrimaryCategoryCode);

只有一个导航属性的关系:

modelBuilder.Entity<OrderLine>()
    .HasRequired(l => l.Product)
    .WithMany()
    .HasForeignKey(l => l.ProductId);

关闭级联删除:

modelBuilder.Entity<Category>()
    .HasMany(c => c.Products)
    .WithRequired(p => p.PrimaryCategory)
    .HasForeignKey(p => p.PrimaryCategoryCode)
    .WillCascadeOnDelete(false);


拥有复合外键的关系:

modelBuilder.Entity<OrderLineNote>()
    .HasRequired(n => n.OrderLine)
    .WithMany(l => l.Notes)
    .HasForeignKey(n => new { n.OrderId, n.ProductId });

 

将没在对象模型中呈示的外键重新命名:

modelBuilder.Entity<Order>()
    .HasRequired(o => o.Person)
    .WithMany(p => p.Orders)
    .IsIndependent()
    .Map(m => m.MapKey(p => p.PersonId, “CustomFkToPersonId”));
 

 

将多对多表中的字段重新命名:

modelBuilder.Entity<Product>()
    .HasMany(p => p.Tags)
    .WithMany(t => t.Products)
    .Map(m =>
        {
            m.MapLeftKey(p => p.ProductId, “CustomFkToProductId”);
            m.MapRightKey(t => t.TagId, “CustomFkToTagId”);
        });
 

表和字段映射

改变字段名:

modelBuilder.Entity<Category>()
    .Property(c => c.Name)
    .HasColumnName(“cat_name”);


改变表名:

modelBuilder.Entity<Category>()
    .ToTable(“MyCategories”);


改变schema中的表名:

modelBuilder.Entity<Category>()
    .ToTable(“MyCategories”, “sales”);


 

继承表映射

单表继承(Table Per Hierarchy,简称TPH)

TPH = “将所有的数据保存在一个表中,使用一个或多个字段的值来识别每行记录所属的类型”

简单的TPH是一个类继承层次结构的默认映射。

带自定义识别字段名称和值的TPH:

modelBuilder.Entity<Product>()
    .Map<Product>(m => m.Requires(“Type”).HasValue(“Current”))
    .Map<DiscontinuedProduct>(m => m.Requires(“Type”).HasValue(“Old”));

每个类型对应一个表(Table Per Type,简称TPT)

TPT = “将基类上属性的所有数据保存在单个表中,将继承类的任何额外数据保存在另外的表中,该表有一个指向基类表的外键”

modelBuilder.Entity<Product>().ToTable(“Products”);
modelBuilder.Entity<DiscontinuedProduct>().ToTable(“OldProducts”);


每个具体类对应一个表(Table Per Concrete Class, 简称TPC)

TPC = “为类层次结构的每个非抽象类型创建一个完全独立的表”

modelBuilder.Entity<Product>().ToTable(“Products”);
modelBuilder.Entity<DiscontinuedProduct>()
    .Map(m =>
        {
            m.MapInheritedProperties();
            m.ToTable(“OldProducts”);
        });

 

结语

在这个贴子里,我们看了若干个使用Code First 流畅 API的例子,在论坛上经常被问的场景会在以后添加进来。

反馈和支持

一如以往,我们非常希望你在这个博客贴子上做评论,给我们提供任何关于流畅API的反馈。

想得到支持的话,请使用实体框架预览产品论坛

 

Rowan Miller
Program Manager
ADO.NET实体框架开发团队

 

发表在 未分类 | 评论关闭

【翻译】EF特性CTP5版: 代码优先示范

【原文地址】EF Feature CTP5: Code First Walkthrough
【原文发表日期】 6 Dec 2010 9:00 PM

我们刚发布了实体框架特性第五个社区技术预览版 (简称CTP5)。 特性CTP5版包括了我们计划在2011年第一个季度以独立的软件包形式发布的新特性的预览内容,希望得到大家的反馈。特性CTP5版建立在随.NET框架4.0和Visual Studio 2010发布的现有实体框架4(简称EF4)的功能之上,是我们先前CTP版本的更新版。

本贴将对代码优先(Code First)开发作一个简介。代码优先允许你使用 C# 或 VB.Net类定义你的模型,可以使用特性(attributes)在你的类和属性上,或者使用流畅(Fluent)API,附加额外的配置。你的模型可以用来生成数据库定义或者映射到现有的数据库上。

映射到现有数据库

在CTP5版本中,我们去除了映射到现有数据库时要做额外配置的需要。如果Code First检测到它指向一个它并没有生成的现有数据库定义,那它就会“信任你”,尝试对该数据库定义使用code first的方法。将Code First指向一个现有数据库最简单的方法是加一个App/Web.config连接字符串,给它一个与你的DbContext继承类同样的名称,例如:

<connectionStrings>
  <add 
    name="MyProductContext" 
    providerName="System.Data.SqlClient" 
    connectionString="Server=.\SQLEXPRESS;Database=Products;Trusted_Connection=true;"/>
</connectionStrings>

这个示范将演示使用 Code First 生成数据库定义,但同样的原理适用于映射到现有的数据库上,除了下面的“第8步: 设置起始化策略”并不适用于现有数据库外。

 

1. 安装 EF CTP5版

如果你还没安装的话,那么你需要安装实体框架特性CTP5

 

2. 创建应用

为简单起见,我们将建造一个基本的console应用,使用Code First来做数据访问:

  • 打开 Visual Studio 2010
  • 文件 -> 新 -> 项目…
  • 从左边菜单中选择 “Windows”,然后 “Console应用”
  • 输入“CodeFirstSample”作其名称
  • 选择 “OK”

 

3. 创建模型

让我们使用类来定义一个非常简单的模型,我就在Program.cs文件里定义这些类,但在实际应用中,你应该将你的类们分离成单独的文件,甚至单独的项目。

在Program.cs文件中的Program类定义下面,我定义了下面2个类:

public class Category
{
    public string CategoryId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public string CategoryId { get; set; }

    public virtual Category Category { get; set; }
} 

 

4. 创建一个上下文(Context)

开始使用类来做数据访问最简洁的方法是,定义一个继承自System.Data.Entity.DbContex的上下文类,对我的模型中的每个类呈示一个类型为DbSet<TEntity>的属性。

现在我们将开始使用CTP5版中的类型,所以我们需要加一个对CTP5程序集的引用:

  • 项目 -> 添加引用…
  • 选择 “.NET” 页
  • 从列表中选择“EntityFramework”
  • 点击 “OK”

你还需要引用现有的实体框架程序集:

  • 项目 -> 添加引用…
  • 选择 “.NET” 页
  • 从列表中选择 “System.Data.Entity”
  • 点击 “OK”

在Program.cs文件的顶部加一个using System.Data.Entity的语句:

using System.Data.Entity;

在我们刚定义的类下面加一个上下文继承类:

public class ProductContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
}

这些就是我们开始保存和获取数据所需的全部代码,很明显,在幕后发生了很多事情,等一会儿我们来看一下其中细节,但首先我们来用用看。

 

5. 读写数据

在我的Program类中的Main方法里我添加了若干代码,如下:

class Program
{
    static void Main(string[] args)
    {
        using (var db = new ProductContext())
        {
            // Add a food category 
            var food = new Category { CategoryId = "FOOD", Name = "Foods" };
            db.Categories.Add(food);
            int recordsAffected = db.SaveChanges();

            Console.WriteLine(
                "Saved {0} entities to the database, press any key to exit.",
                recordsAffected);

            Console.ReadKey();
        }
    }
} 

你现在可以运行应用,会看到插入了新的Category。

我的数据在哪里?

按约定,DbContext会在localhost\SQLEXPRESS中为你创建一个数据库。数据库的名称是根据你的上下文继承类的全名来定的,在我们的情况下,数据库名为“CodeFirstSample.ProductContext”,我们将在本示范的稍后看一下改变这个行为的方法。

模型的发现

DbContext通过查看我们定义的DbSet属性,推断出包括在模型中的类。然后它会使用默认的Code Firs约定,找出主键,外键等。在CTP5版中实现的全套约定在这个约定设计博客贴子中有详细的讨论。

 

6. 读写更多的数据

让我们在刚编写的程序中再多加一些代码,来展示更多的功能。我们将利用DbSet类中的Find方法,根据主键查询一个实体。如果没找到匹配对象,那么Find方法会返回null。我们还将利用LINQ对在Food分类中的所有产品作查询,并将结果按name的字母顺序排列。查询使用现有的LINQ to Entities提供器,所以它支持EF4中ObjectSet/ObjectQuery同样的查询。

将我们刚编写的Main方法替换成下列代码:

class Program
{
    static void Main(string[] args)
    {
        using (var db = new ProductContext())
        {
            // Use Find to locate the Food category 
            var food = db.Categories.Find("FOOD");
            if (food == null)
            {
                food = new Category { CategoryId = "FOOD", Name = "Foods" };
                db.Categories.Add(food);
            }

            // Create a new Food product 
            Console.Write("Please enter a name for a new food: ");
            var productName = Console.ReadLine();

            var product = new Product { Name = productName, Category = food };
            db.Products.Add(product);

            int recordsAffected = db.SaveChanges();

            Console.WriteLine(
                "Saved {0} entities to the database.",
                recordsAffected);

            // Query for all Food products using LINQ 
            var allFoods = from p in db.Products
                            where p.CategoryId == "FOOD"
                            orderby p.Name
                            select p;

            Console.WriteLine("All foods in database:");
            foreach (var item in allFoods)
            {
                Console.WriteLine(" - {0}", item.Name);
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
} 

 

7. 改变数据库名称

如果你想要改变为你自动生成的数据库的名称,有一个方法是改动你的DbContext继承的构造器,指定新的数据库的名称。

譬如说,我们想要把数据库名称改为“MyProductDatabase”,我们可以给我们的上下文继承类加一个默认构造器,将这个名字传给DbContext:

public class ProductContext : DbContext
{
    public ProductContext()
        : base("MyProductDatabase")
    { }

    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
} 
改变数据库的其他方法

还有若干种方法可以指定应该连接哪个数据库,在将来我们会在单独的贴子中做详述。

  • App.config 文件中的连接字符串
    在App.Config文件中创建与你的上下文同名的连接字符串。
  • DbConnection
    有一个构造器接受DbConnection。
  • 替换默认的约定
    基于上下文名称来定位数据库的这个约定是AppDomain范围的设置,你可以通过System.Data.Entity.Database.DbDatabase.DefaultConnectionFactory的静态属性来做改变。

 

8. 设置起始化策略

在下一节里,我们讲开始改变我们的模型,即意味着数据库定义也需要改变。目前还没有开箱即可用(‘out of the box’)的方案可以原地演变你现有的数据库定义。数据库演变是我们正研究的东西,最近一篇设计博客贴子提供了我们目前的趋向的一个例子。

但是,有机会在上下文第一次在一个AppDomain里运行时,运行一些定制的代码来初始化数据库。这在你想要插入初始数据用于做测试运行时会非常方便,在模型改变后重新创建数据库时也会非常有用。在CTP5版本中,我们包含了几个策略,你可以插接使用,但你也可以编写定制的策略。

在Program.cs的顶部,加一个 using System.Data.Entity.Database 语句:

using System.Data.Entity.Database;

在本示范中,我们只想要在模型改变后,删除和重建数据库,所以在Program类的Main方法的顶部,我加了下述代码:

DbDatabase.SetInitializer<ProductContext>(
new DropCreateDatabaseIfModelChanges<ProductContext>());

 

9. 数据注释(Data Annotations)

到目前为止,我们仅是让EF通过默认的约定去发现模型,但有时候当我们的类并不遵循约定时,我们需要能够做进一步的配置。对此,有2个选项,在本节中,我们将看一下数据注释,Code First的流畅API将在另外一篇贴子中讨论

让我们在模型中加一个Supplier类:

public class Supplier
{
    public string SupplierCode { get; set; }
    public string Name { get; set; }
}

我们还需在上下文继承类中加一个集合:

public class ProductContext : DbContext
{
    public ProductContext()
        : base("MyProductDatabase")
    { }

    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Supplier> Suppliers { get; set; }
}

至此,如果我们运行应用的话,我们会得到一个 InvalidOperationException 异常,说是“ EntityType ‘Supplier’ has no key defined. Define the key for this EntityType.” (实体类型 ‘Supplier’ 没有定义主键,请为此实体类定义主键),因为EF无法知道SupplierCode应该是Supplier的主键。

我们将使用数据注释,先需要加一个引用:

  • 项目 -> 添加引用…
  • 选择“.NET” 页
  • 从列表中选择“System.ComponentModel.DataAnnotations”
  • 点击 “OK

在Program.cs的顶部加一个using语句:

using System.ComponentModel.DataAnnotations;

现在,我们可以给SupplierCode属性加一个注释,表示它是主键:

public class Supplier
{
    [Key]
    public string SupplierCode { get; set; }
    public string Name { get; set; }
}

CTP5版支持的注释的完整列表如下:

  • KeyAttribute
  • StringLengthAttribute
  • MaxLengthAttribute
  • ConcurrencyCheckAttribute
  • RequiredAttribute
  • TimestampAttribute
  • ComplexTypeAttribute
  • ColumnAttribute
    置于一个属性上,指定其字段名,序数和数据类型
  • TableAttribute
    置于一个类上,指定其数据表名和定义
  • InversePropertyAttribute
    置于一个导航属性上,指定代表关系另一端的属性
  • ForeignKeyAttribute
    置于一个导航属性上,指定代表关系外键的属性
  • DatabaseGeneratedAttribute
    置于一个属性上,指定数据库该如何为该属性生成值(Identity, Computed 或者 None)
  • NotMappedAttribute
    置于一个属性或类上,将其排除在数据库外

 

10. 验证

在CTP5版本中,我们引进了一个新的特性,在尝试保存到数据库前,会验证实例数据是否满足数据注释。

让我们加一个注释,指定Supplier.Name的长度必须在5到20个字符之间:

public class Supplier
{
    [Key]
    public string SupplierCode { get; set; }

    [MinLength(5)]
    [MaxLength(20)]
    public string Name { get; set; }
}

在Program.cs的顶部加一个using语句:

using System.Data.Entity.Validation;

让我们改变Main方法,插入一些不合法的数据,捕捉住异常,显示任何错误的信息:

class Program
{
    static void Main(string[] args)
    {
        DbDatabase.SetInitializer<ProductContext>(
new DropCreateDatabaseIfModelChanges<ProductContext>()); using (var db = new ProductContext()) { var supplier = new Supplier { Name = "123" }; db.Suppliers.Add(supplier);
try { db.SaveChanges(); } catch (DbEntityValidationException ex) { foreach (var failure in ex.EntityValidationErrors) { Console.WriteLine(
"{0} failed validation",
failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors) { Console.WriteLine(
"- {0} : {1}",
error.PropertyName,
error.ErrorMessage); } } } Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } }

如果运行应用,我们将看到显示了下列信息:

CodeFirstSample.Supplier failed validation
- Name : The field Name must be a string or array type with a minimum length of ‘5’.

Press any key to exit.(CodeFirstSample.Supplier验证失败,Name : 字段Name必须是个字符串或数组类型,最少长度为5,点击任何一键退出)

结语

在本示范中,我们看了如何使用EF特性CTP5版做代码优先(Code First)开发,我们看了如何定义和配置模型,保存和获取数据,配置数据库连接,随着模型的演变更新数据库定义,在写入数据库前做数据验证。

流畅API

除了数据注释外,Code First还呈示了一个用于做配置的流畅API,相关内容在另一个博客贴子里讨论。

反馈和支持

一如以往,我们非常希望你在这个博客贴子上做评论,给我们提供任何关于代码优先(Code First)的反馈。

想得到支持的话,请使用实体框架预览产品论坛

 

Rowan Miller
Program Manager
ADO.NET实体框架开发团队

发表在 未分类 | 评论关闭

《Windows Phone 7 Developer Guide 》RC版

微软模式和实践开发团队推出《Windows Phone 7 Developer Guide 》,可在线阅读:

http://msdn.microsoft.com/en-us/library/gg490765.aspx

相关代码在:

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=15718049-f993-4d54-ba7b-72e0e82c16cd&displaylang=en

 

也可从CodePlex下载WORD版本和代码:

http://wp7guide.codeplex.com/

发表在 未分类 | 评论关闭

【翻译】EF特性CTP5版: 使用DbContext做模型和数据库优先开发

【原文地址】EF Feature CTP5: Model & Database First with DbContext
【原文发表日期】 6 Dec 2010 9:00 PM

我们刚发布了实体框架特性第五个社区技术预览版 (简称CTP5)。 特性CTP5版包括了我们计划在2011年第一个季度以独立的软件包形式发布的新特性的预览内容,希望得到大家的反馈。特性CTP5版建立在随.NET框架4.0和Visual Studio 2010发布的现有实体框架4(简称EF4)的功能之上,是我们先前CTP版本的更新版。

本贴将对在Visual Studio中使用实体数据模型设计器来做模型优先(Model First)和数据库优先(Database First)的开发提供一个简介。

 

1. 安装 EF CTP5

如果你还没安装的话,那么你需要安装实体框架特性CTP5

 

2. 创建应用

为简单起见,我们将建造一个基本的console应用,使用DbContext来做数据访问:

  • 打开 Visual Studio 2010
  • 文件 -> 新 -> 项目…
  • 从左边菜单中选择 “Windows”,然后 “Console应用”
  • 输入“ModelFirstSample”作其名称
  • 选择“OK”

 

3. 创建模型

先往项目中加一个实体数据模型

  • 项目 –> 添加新项…
  • 从左边菜单选择‘数据’
  • 从列表中选择‘ADO.NET 实体数据模型’
  • 将模型命名为‘PersonModel.edmx’
  • 点击‘添加’

在这个示范中,我们将使用模型优先(Model First),但如果你要映射到现有数据库的话,你现在应该选择‘从数据库生成’,按提示走下去,然后跳到第4步。

  • 选择 ‘空白模型(Empty model)’
  • 点击‘完成’

让我们在模型中加一个Person实体:

  • 在设计表面上,右击 –> 添加 –> 实体
  • 将实体命名为‘Person’
  • 点击 ‘OK’
  • 在Person实体上右击 –>添加 –> 标量属性
  • 将属性命名为‘FullName’

image

至此,我们定义了模型,我们可以生成一个数据库定义来保存数据:

  • 在设计表面上右击 –> 从模型生成数据库
  • 点击 ‘新连接…’
  • 指定你希望创建的数据库的细节
  • 点击 ‘OK’
  • 如果提示生成数据库,点击 ‘是’
  • 点击 ‘下一步’ 然后 ‘完成’
  • 在生成的脚本窗口,右击 –> 执行 SQL…
  • 指定数据库服务器, 然后点击 ‘连接’

 

4. 替换成 DbContext 代码生成

PersonModel目前生成了一个ObjectContext继承类,所有的实体类都继承于EntityObject,我们想要利用简单的DbContext API:

  • 在设计表面上,右击Right Click –> 添加代码生成项…
  • 从左边菜单中选择‘代码’
  • 选择 ‘ADO.NET DbContext 生成器’
  • 将其命名为‘PersonModel.tt’
  • 点击 ‘添加’

你会注意到2个东西加到了你的项目中:

  • PersonModel.tt
    这个模板针对你模型中的每个实体类生成非常简单的POCO类
  • PersonModel.Context.tt
    这个模板生成一个DbContext继承类,用于查询和持久数据

 

5. 读写数据库

该到访问数据的时候了,我在Program.cs文件中的Main方法里添加了若干代码,如下:

class Program
{
    static void Main(string[] args)
    {
        using (var db = new PersonModelContainer())
        {
            // Save some data
            db.People.Add(new Person { FullName = "Bob" });
            db.People.Add(new Person { FullName = "Ted" });
            db.People.Add(new Person { FullName = "Jane" });
            db.SaveChanges();

            // Use LINQ to access data
            var people = from p in db.People
                            orderby p.FullName
                            select p;

            Console.WriteLine("All People:");
            foreach (var person in people)
            {
                Console.WriteLine("- {0}", person.FullName);
            }

            // Change someones name
            db.People.First().FullName = "Janet";
            db.SaveChanges();
        }

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }
}

 

结语

在这个示范中,我们看了一下如何使用EF特性CTP5版做模型优先开发,先建立了模型,生成了数据库,替换到DbContext代码生成,然后保存和查询数据。

反馈和支持

一如以往,我们非常希望你在这个博客贴子上做评论,给我们提供任何反馈。

想得到支持的话,请使用实体框架预览产品论坛

 

Rowan Miller
Program Manager
ADO.NET实体框架开发团队

发表在 未分类 | 评论关闭

实体框架特性CTP5发布了

可在这里下载:

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35adb688-f8a7-4d28-86b1-b6235385389d

这个新的CTP版本包括了对Code First特性的更新和DbContext API的简化。相关细节参阅ADO.NET团队博客:

http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-released.aspx

正式版本大概会在2011年的第一季度发布。

发表在 未分类 | 评论关闭

如何把一个Windows Phone 7 Twitter应用转换成新浪微博客户端

大家也许知道,我最近被开心拉下了水,一直在新浪微博灌水,欢迎大家去拍砖:

http://t.sina.com.cn/timeflieslikeanarrow

Windows Phone 7推出后不久,就买了一个三星Focus牌手机,可惜无法登录新浪微博的手机版,登录时得到这样的错误:

Can’t download file! Windows Phone doesn’t support .php files

直觉是微博的登录网页也许没设置好MIME类型。

所以在想也许应该写个客户端,找了一下,博客园有几篇文章,用的都是Basic Authentication (意味着你需要记录用户的帐号和密码,而且每次访问时都要发送帐号/密码)。新浪推荐使用oAuth,也提供了一个网友维护的基于OAuth认证的C#  SDK,不是很喜欢。想到新浪微博的API与Twitter非常相似,所以想找一个.NET或Windows Phone 7 Twitter应用。找到了微软的Sam Jarawan写的博客系列《Building a ‘real’ Windows Phone Twitter App》和他的Twitt应用:

http://samjarawan.blogspot.com/2010/10/building-real-windows-phone-twitter-app_07.html

发现真的很容易转成可以访问新浪微博的客户端。现将转换步骤列出如下(假定你已经安装了Windows Phone 7开发工具等,也申请了新浪微博应用的App Key和Secret Key):

1. 去 http://twitt.codeplex.com/ 下载Twitt Part 7应用源码

2.  在VS2010中打开。修改Common目录下的TwitterSettings类,把其中的Rest URLs改成新浪微博的(参考 http://open.t.sina.com.cn/wiki/index.php/API%E6%96%87%E6%A1%A3),具体为

public static string RequestTokenUri = “http://api.t.sina.com.cn/oauth/request_token”;
public static string OAuthVersion = “1.0”;
public static string CallbackUri = “http://blog.joycode.com/saucer“;
public static string AuthorizeUri = “http://api.t.sina.com.cn/oauth/authorize”;
public static string AccessTokenUri = http://api.t.sina.com.cn/oauth/access_token;

(注:好像https有问题,所以用了http)

同时将ConsumerKey和ConsumerKeySecret改成新浪微博提供的App Key和Secret Key。

Twitt使用了bing.com作为CallbackUri,你也可以将其改成你自己的URL,在这里我把它改成了自己博客的地址。Twitt用了一个浏览器控件,通过这个URL来获取oauth_token 和 oauth_verifier ,进而获取access_token(细节参看 http://open.t.sina.com.cn/wiki/index.php/Oauth)。

还有几个地方硬写了“http://api.twitter.com”,你要将其改成对应于新浪微博的URL,或者重构一下代码,将所有URL集中在TwitterSettings类中。

3. 重新编译,确认无错。在target下拉框中,选择Windows Phone 7 Emulator,然后按F5。当新浪微博授权页面出现时,输入你自己的新浪微博的帐号和密码,这时会出现:“获取到授权码:。。。。。(6个数字)“,而没有重新定向返回到应用。这好像是新浪微博授权机制的一个小bug,并不记住“/request_token”时传给服务器的callback URL。为解决这个问题,需要在Views目录下TwitterAuthPage类中的TwitterRequestTokenCompleted方法中在if语句前加一行(在此折腾了好久,反复阅读新浪微博文档,也麻烦了宝玉,谢谢宝玉!),

authorizeUrl += “&oauth_callback=” + System.Net.HttpUtility.UrlEncode(TwitterSettings.CallbackUri);

重新编译运行,就没问题了。新浪授权后,也许会得到几个对话框埋怨错误,但点击OK后就没问题了,也可以去settings一列下点击Refresh按钮。就这么简单!

 

Twitt使用了Hammock for REST(http://hammock.codeplex.com/ )做oAuth认证,这是个非常棒的.NET REST 库,极大地简化了对REST服务的访问,高度推荐!

下面是一张做了一些汉化后的截图:

 

当然Twitt并没有完全实现微博的功能,但可以作为一个很好的起点。该应用里面涉及的内容很多,建议有兴趣者对Sam Jarawan的七篇文章(作者描写的过程非常详细)从头研究起,跟着做一遍,保证受益多多。

发表在 未分类 | 评论关闭

Windows Phone 7 开发资源

下面是我陆续在新浪微博上贴出的Windows Phone 7 开发资源:

1. 微软马宁的《Windows Phone 7中的IronRuby》:http://sinaurl.cn/h4sxzY 他的博客上还有其他一些Windows Phone 7的教程

2. Windows Phone 7样例应用PathFinder: http://sinaurl.cn/h4EuqQ 【来源】Windows Phone 7 and Artificial Intelligence (http://sinaurl.cn/h4kTVd

3. Windows Phone 7 资源链接大全:http://sinaurl.cn/h4DFPD

4. oData的.NET, Silverlight, 和 Windows Phone 7 客户端库开源 : http://sinaurl.cn/h4DFvy

5. 《Getting Started with Windows Phone 7 Development》 (http://sinaurl.cn/h4eveL ) , 《Migrating a Silverlight Application to Windows Phone 7》 (http://sinaurl.cn/h4eZlz

6. 十个针对超级新手的Windows Phone 7开发录像:http://sinaurl.cn/h4r8hw

7. CodePlex上还有几个针对WP7的开源数据库: Sterling ( http://sinaurl.cn/h9e0IS ) 和 winphone7db (http://sinaurl.cn/hC27Xx )。还有一个叫Perst的面向对象的数据库 (http://sinaurl.cn/hC2UBO

8. WP7的存储机制是Isolated Storage, Sean McAlinden推出了一个称为Rapid Repository的数据库开源项目,简化了在WP7上的数据存储:http://sinaurl.cn/h43zx0

9. Shawn Wildermuth的《Architecting WP7 》系列文章: http://sinaurl.cn/hCAuXF

10. 微软App Hub的Windows Phone例程: http://sinaurl.cn/h4Wn2S

11. 微软App Hub的为WP7开发游戏的教育路线图:第一阶段:Platform;第二阶段:Performance;第三阶段:Polish。提供了若干个例程: http://sinaurl.cn/h6I6NZ 。里面有一篇文章: Intro to C# From Objective-C and Java (http://sinaurl.cn/h6IKKo

发表在 未分类 | 评论关闭

Charles Petzold的《Windows Phone 7编程》电子书正式版发布了

可从Charles Petzold的网站上下载:

http://www.charlespetzold.com/phone/index.html

发表在 未分类 | 评论关闭