2009-08-19 58 views
4

我正在学习ASP.NET MVC。我正在关注asp.net的基本教程之一。由于我并不总是遵循教程,所以我决定使用GUID作为标识列而不是整数。一切工作正常,直到我通过MVC应用程序添加新记录到数据库。当我添加新记录时,它插入了一个空白的GUID而不是生成的GUID。这里是处理插入代码隐藏的段:使用GUID作为与ASP.NET MVC的数据库中的ID

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Exclude = "id")]Movie movieToCreate) 
{ 
    try 
    { 
     _entities.AddToMovieSet(movieToCreate); 
     _entities.SaveChanges(); 

     return RedirectToAction("Index"); 
    } 
    catch 
    { 
     return View(); 
    } 
} 

[Bind(Exclude = "id")]“线忽略”的ID列,因为它是自动生成。在教程中,ID是自动递增的,但我认为这是因为它是一个整数。我尝试在此方法中添加一行:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Exclude = "id")]Movie movieToCreate) 
{ 
    try 
    { 
     movieToCreate.id = Guid.NewGuid(); 
     _entities.AddToMovieSet(movieToCreate); 
     _entities.SaveChanges(); 

     return RedirectToAction("Index"); 
    } 
    catch 
    { 
     return View(); 
    } 
} 

但是,ID仍然是空的GUID。任何人都可以向我提供一些信息,说明这是为什么,也许如何解决它?

+0

显然删除'[Bind(Exclude)]'并保留'Guid.NewGuid()'修复了这个问题。我仍然想知道为什么ID自动增加,但GUID不是自动生成的。 – Anders 2009-08-19 19:58:24

+0

这两个值都是在服务器上生成的。但EF只能看到int,因为SQL Server提供程序从服务器返回生成的ints,但没有生成ID。如果你放弃了上下文并重新查询,你会看到两者。 – 2009-08-20 01:57:39

+0

...但不生成ID。 - > ...但不生成GUID。 – 2009-08-20 01:58:17

回答

6

您可以使用自定义ModelBinder。我了解了关于here的那些。

public class MyClassBinder : DefaultModelBinder { 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) { 
     var model = (Movie)base.CreateModel(controllerContext, bindingContext, modelType); 
     model.id = Guid.NewGuid(); 
     return model; 
    } 
} 

和你的动作控制器将是:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult MyAction(Movie movieToCreate) { 
    // movie should have a new guid in the id 
    _entities.AddToMovieSet(movieToCreate); 
    _entities.SaveChanges(); 
} 

而且你需要注册在Global.asax中的粘结剂:

protected void Application_Start() { 
    RegisterRoutes(RouteTable.Routes); 
    ModelBinders.Binders.Add(typeof(Movie), new MyClassBinder()); 
} 
+0

我会在自己的文件中创建这个活页夹吗?如果是这样,应该在哪里放置?在我的控制器相同的目录中?感谢您的信息和链接! – Anders 2009-08-19 20:24:32

+1

我把我的自定义活页夹放在我的MVC应用程序的Models文件夹中的一个名为Binders的文件夹中。 – 2009-08-19 20:32:15

+0

非常好,谢谢你! – Anders 2009-08-19 21:01:52

0

在.net 3.5的SQL Server EF提供商SP1无法检索服务器生成的GUID,因为SQL Server的陈旧版本无法支持该功能。所以你需要生成GUID客户端,直到这个限制被修复。

可以在模型联编程序中执行此操作,正如swilliams所示,但恕我直言联编程序只应绑定请求中的数据。所以我在我的模型层上做。但无论哪种方式将工作。

+0

你能否详细说明你的方法?当我正在学习时,我想知道我可以使用的所有选项。谢谢! – Anders 2009-08-19 21:02:31

+2

简单,真的。在插入新记录时,在调用SaveChanges()之前,我使用代码(使用Guid.NewGuid())设置ID。所有这些都是在与包含控制器和视图的程序集分离的模型程序集内完成的。 – 2009-08-19 21:07:36

+0

所以基本上我通过从Movie参数中删除[Bind(Execute)]来做什么? – Anders 2009-08-19 21:28:23

1

SQL数据库中的ID字段的类型是什么?它是唯一标识符吗? 如果不是,请将其更改为uniqueidentifier并使其自动生成。 结账this文章。

+0

他已经做到了;仔细阅读这个问题。 EF的SQL Server提供程序不会将自动生成的GUID转发给客户端。 – 2009-08-19 21:08:34

+0

哎哟...我的坏.. – Sorantis 2009-08-19 21:50:17

0

你可以像下面一样更新你的Create Action,并且给它新的guid。然后它会自动转移到后置操作。所有代码将如下所示:

public ActionResult Create() 
{ 
    Movie movietocreate = new Movie(); 

    movietocreate.id = Guid.NewGuid(); //you set the new guid here 

    return View(movietocreate); 
} 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create(Movie movieToCreate) 
{ 
    try 
    { 
     _entities.AddToMovieSet(movieToCreate); 
     _entities.SaveChanges(); 

     return RedirectToAction("Index"); 
    } 
    catch 
    { 
      return View(); 
    } 
} 
相关问题