Sử dụng SQL Server 2008 và SQL Server 2005 và ngày giờ


118

Tôi đã xây dựng một mô hình khung thực thể dựa trên cơ sở dữ liệu năm 2008. Tất cả đều hoạt động tốt so với cơ sở dữ liệu năm 2008. Khi tôi cố gắng cập nhật thực thể trên cơ sở dữ liệu 2005, tôi gặp lỗi này.

Phiên bản SQL Server đang sử dụng không hỗ trợ kiểu dữ liệu 'datetime2

Tôi đặc biệt không sử dụng bất kỳ tính năng nào của năm 2008 khi tôi xây dựng cơ sở dữ liệu. Tôi không thể tìm thấy bất kỳ tham chiếu nào đến datetime2 trong mã. Và, có cột được định nghĩa là "datetime" trong cơ sở dữ liệu.

Câu trả lời:


189

Một google nhanh chóng chỉ cho tôi những gì trông giống như giải pháp .

Mở EDMX của bạn trong trình chỉnh sửa tệp (hoặc “mở bằng…” trong Visual Studio và chọn Trình chỉnh sửa XML). Ở trên cùng, bạn sẽ tìm thấy mô hình lưu trữ và nó có thuộc tính ProviderManifestToken. Điều này phải có giá trị 2008. Thay đổi thành 2005, biên dịch lại và mọi thứ hoạt động.

LƯU Ý: Bạn sẽ phải làm điều này mỗi khi cập nhật mô hình từ cơ sở dữ liệu.


2
Tôi đã bỏ phiếu điều này do nhầm lẫn, bỏ phiếu điều đó, nhưng bây giờ không thể làm những gì tôi thực sự muốn làm là bỏ phiếu nó! Cảm ơn bạn đã tìm thấy vấn đề. Nếu tôi hiểu đúng, giá trị có thay đổi từ năm 2005 đến năm 2008 do cập nhật mô hình từ cơ sở dữ liệu, nơi cơ sở dữ liệu là DB SQL 2008 không? Trong môi trường của tôi, máy nhà phát triển của tôi có SQL 2008, nhưng môi trường thử nghiệm có 2005 (sản xuất cũng có). Cho đến khi chúng tôi chuyển sang năm 2008, tôi có đúng khi cho rằng điều này sẽ tiếp tục xảy ra không?
jamiebarrow

Tôi thường đặt điều này thành 2005, là cơ sở dữ liệu sản xuất; Tôi đang sử dụng 2008 để phát triển. 2008 là tương thích ngược nên không có vấn đề gì. Ngoài ra, điều này sẽ được thay đổi lại sau khi cập nhật / tạo. Tôi luôn xác nhận điều này khi kiểm tra EDMX sau khi trải nghiệm cay đắng.
Richard Harrison

bản sửa lỗi này không làm việc cho tôi ?? Forum.asp.net/p/1770522/4838628.aspx/…
Vua xứ Wales

Nếu điều này xảy ra trong LightSwitch, hãy xem bài đăng trên blog của tôi giải thích cách sửa lỗi trong tệp lsml (vì không có quyền truy cập trực tiếp vào tệp edmx trong LS): lightswitchcentral.net.au/Blog/tabid/83/EntryId/27/ …
Yann Duran

Đó là giải pháp duy nhất nhưng bạn nên lưu ý rằng bạn cần phải làm điều này mỗi khi bạn sửa đổi edmx vì nó sẽ tự hoàn nguyên
Dave Hogan

11

Xem nhanh dòng:

<Schema Namespace="Foobar.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" >

10

Điều này rất khó chịu và tôi rất ngạc nhiên khi MS quyết định không thực hiện nó để bạn có thể nhắm mục tiêu một phiên bản SQL nhất định. Để đảm bảo rằng chúng tôi đang nhắm đến năm 2005, tôi đã viết một ứng dụng console đơn giản và gọi nó trong bước PreBuild.

Bước tạo trước trông giống như sau:

$(SolutionDir)Artifacts\SetEdmxVer\SetEdmxSqlVersion $(ProjectDir)MyModel.edmx 2005

Mã ở đây:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace SetEdmxSqlVersion
{
    class Program
    {
        static void Main(string[] args)
        {
            if (2 != args.Length)
            {
                Console.WriteLine("usage: SetEdmxSqlVersion <edmxFile> <sqlVer>");
                return;
            }
            string edmxFilename = args[0];
            string ver = args[1];
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(edmxFilename);

            XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDoc.NameTable);
            mgr.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");
            mgr.AddNamespace("ssdl", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");
            XmlNode node = xmlDoc.DocumentElement.SelectSingleNode("/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema", mgr);
            if (node == null)
            {
                Console.WriteLine("Could not find Schema node");
            }
            else
            {
                Console.WriteLine("Setting EDMX version to {0} in file {1}", ver, edmxFilename);
                node.Attributes["ProviderManifestToken"].Value = ver;
                xmlDoc.Save(edmxFilename);
            }
        }
    }
}

@Vance cảm ơn rất nhiều, hoàn hảo. Hơi chậm, vì tôi có ba tệp edmx cần thay đổi, vì vậy có thể thêm cấu hình giải pháp chỉ để hoàn nguyên sau khi triển khai và xóa nó khỏi bản dựng thông thường. Sẽ đăng câu trả lời ngay bây giờ cùng với thông tin về việc sử dụng công cụ hữu ích này trong BeforeBuild (hoặc AfterBuild) thay vì xây dựng trước. Đánh giá rất cao.
MemeDeveloper

3

Sử dụng ứng dụng bảng điều khiển tiện dụng của @ Vance ở trên, tôi đã sử dụng phần sau làm sự kiện BeforeBuild

<Target Name="BeforeBuild">
    <!--Check out BD.edmx, Another.edmx, all configs-->
    <Exec Command="$(SolutionDir)\Library\tf checkout /lock:none $(ProjectDir)Generation\DB.edmx" />
    <Exec Command="$(SolutionDir)\Library\tf checkout /lock:none $(ProjectDir)Generation\Another.edmx" />
    <!--Set to 2008 for Dev-->
    <Exec Condition=" '$(Configuration)' == 'DEV1' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2008" />
    <Exec Condition=" '$(Configuration)' == 'DEV1' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2008" />
    <Exec Condition=" '$(Configuration)' == 'DEV2' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2008" />
    <Exec Condition=" '$(Configuration)' == 'DEV2' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2008" />
    <!--Set to 2005 for Deployments-->
    <Exec Condition=" '$(Configuration)' == 'TEST' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2005" />
    <Exec Condition=" '$(Configuration)' == 'TEST' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2005" />
    <Exec Condition=" '$(Configuration)' == 'PRODUCTION' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\DB.edmx 2005" />
    <Exec Condition=" '$(Configuration)' == 'PRODUCTION' " Command="$(SolutionDir)Library\SetEdmxSqlVersion $(ProjectDir)Generation\Another.edmx 2005" />
  </Target>

Điều này rất tiện dụng, vì tránh được việc triển khai lại gây phiền nhiễu. Cảm ơn đã chia sẻ Vance.

Tôi đã thêm TF.exe vào thư mục giải pháp Thư viện và điều này hữu ích, vì bây giờ tôi có thể kiểm tra các tệp edmx trước khi cố gắng chỉnh sửa chúng, như một phần của bản dựng. Ngoài ra, tôi đã thêm điều này với các điều kiện, để nó đặt thành 2005 cho các triển khai tới máy chủ và trở lại 2008 cho các cấu hình sln máy Dev. Ngoài ra, bạn cần thêm (các) tệp SetEdmxSqlVersion.exe (và .pdb) thực tế vào thư mục Thư viện (hoặc bất kỳ nơi nào khác mà bạn muốn giữ các bit này).

Cảm ơn @Vance rất nhiều. Thực sự gọn gàng, tiết kiệm thời gian lớn và giữ cho các bản dựng của tôi hoàn toàn tự động và không đau :)


2

Gặp sự cố tương tự với 2012 so với 2008. Nó có thể được giải quyết bằng sự kiện BeforeBuild sử dụng XmlPeek và XmlPoke:

   <Target Name="BeforeBuild">
      <XmlPeek XmlInputPath="$(ProjectDir)MyModel.edmx"
               Namespaces="&lt;Namespace Prefix='edmx' Uri='http://schemas.microsoft.com/ado/2009/11/edmx'/&gt;&lt;Namespace Prefix='ssdl' Uri='http://schemas.microsoft.com/ado/2009/11/edm/ssdl'/&gt;"
               Query="/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema/@ProviderManifestToken">
         <Output TaskParameter="Result" ItemName="TargetedSQLVersion" />
      </XmlPeek>

      <XmlPoke Condition="@(TargetedSQLVersion) != 2008"
               XmlInputPath="$(ProjectDir)MyModel.edmx"
               Namespaces="&lt;Namespace Prefix='edmx' Uri='http://schemas.microsoft.com/ado/2009/11/edmx'/&gt;&lt;Namespace Prefix='ssdl' Uri='http://schemas.microsoft.com/ado/2009/11/edm/ssdl'/&gt;"
               Query="/edmx:Edmx/edmx:Runtime/edmx:StorageModels/ssdl:Schema/@ProviderManifestToken"
               Value="2008">
      </XmlPoke>
   </Target>

Nếu bạn không thích thay thế tự động, bạn có thể chỉ cần thay thế tác vụ XmlPoke bằng một tác vụ Lỗi.


Điều này tốt hơn nhiều so với việc sử dụng một tệp thực thi bên ngoài, cho phép MSBuild xử lý tất cả các yêu cầu bên trong. Tất cả điều này có thể được xâu chuỗi dễ dàng thông qua CallTargetcác nhiệm vụ mục tiêu tạo trước có điều kiện tùy thuộc vào cấu hình xuất bản / xây dựng. (EG chỉ thay đổi khi triển khai sang môi trường sql2005)
admalledd

1

Vì lợi ích của những người gặp phải vấn đề tương tự nhưng đang sử dụng Code First , hãy xem câu trả lời của tôi tại đây về cách thay đổi ProviderManifestTokentrong Code First. Nó liên quan đến việc tạo DbModelBuilderthủ công và chuyển một DbProviderInfothể hiện (với mã thông báo thích hợp) khi gọi Buildphương thức của trình tạo mô hình .


Tôi nghĩ rằng thiết lập Type System Version=SQL Server 2005trong chuỗi kết nối cũng có thể làm việc
code4j

0

Giải pháp tốt hơn với tôi là thay vì chỉnh sửa thủ công tệp EDMX thì chỉ cần mở edmx ở chế độ thiết kế và trong menu ngữ cảnh "Cập nhật mô hình từ cơ sở dữ liệu ...". Tất nhiên, bạn phải trỏ đến phiên bản SQL bên phải bất kể điều này dành cho bạn.


1
Tôi nghĩ rằng đây là vấn đề của OP của - ông đã phát triển chống lại một lệnh SQL địa phương năm 2008 nhưng sau đó triển khai tới SQL 2005.
StuartLC

Điều này hoạt động trừ khi bạn không có quyền truy cập vào phiên bản SQL 2005.
Darcy

1
Một bất lợi lớn là nó là một bước thủ công, và do đó sẽ bị lãng quên.
Jowen

0

Chúng tôi đã gặp lỗi này trên SQL2005 v.3, trong đó chúng tôi không gặp lỗi này trên SQL2005 v.4.

Thêm SQL2005 vào chuỗi kết nối đã khắc phục sự cố cụ thể của chúng tôi.

Chúng tôi vẫn chưa xác định lý do tại sao và không muốn sửa đổi mã để cung cấp mã thông báo như đã giải quyết ở trên (sự cố được hiển thị trong quá trình triển khai).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.