2011-12-30 21 views

回答

4

實體框架不知道給定的視圖是否可更新或不可更新,因此它添加了該元素以防止框架嘗試針對不可更新的視圖生成查詢。

如果您的視圖是可更新的,您可以簡單地將您的視圖的EntitySet定義中的元素從您的.edmx的StorageModel部分內部移除,並且正常的更新處理將與任何其他表一樣工作。

如果您的視圖不可更新,則必須通過「修改函數映射」自己提供更新邏輯。修改函數映射調用您的.edmx的StorageModel部分中定義的函數。該函數可能包含數據庫中存儲過程的名稱和參數,或者您可以使用「定義命令」來直接在.edmx的StorageModel部分的函數定義中寫入插入,更新或刪除語句。

在這兩個選項中,如果你的視圖是可更新的(它聽起來可能是這樣),最簡單的就是刪除設計者插入的內容。

+1

確認,需要在你的桌上PK(一個複合PK將做)。刪除定義查詢會讓事情變得更糟。 – StuartLC 2012-08-06 07:12:16

+0

我有這個問題,但如果我從EDMX中刪除DefiningQuery部分,下一次我從數據庫更新模型時會重新生成此部分? – Jerry 2013-06-05 17:24:35

25

確保您的表具有主鍵!

3

更新:最近我得到了一些讚揚,所以我想讓人們知道我給出的建議不是最好的。由於我最初開始關注在舊的無鑰匙數據庫上使用Entity Framework,我逐漸意識到,BY FAR可以做的最好的事情是通過反向代碼優先做到這一點。關於如何做到這一點,有幾篇很好的文章。只需遵循它們,然後當您想爲其添加密鑰時,使用數據註釋來「僞造」密鑰。

例如,假設我知道我的表Orders,雖然它沒有主鍵,但確保每個客戶只有一個訂單號。由於這些都是餐桌上的前兩列,我設置代碼第一類是這樣的:

[Key, Column(Order = 0)] 
    public Int32? OrderNumber { get; set; } 

    [Key, Column(Order = 1)] 
    public String Customer { get; set; } 

通過這樣做,你基本上是僞造的EF,以爲有由聚集鍵OrderNumber和Customer。這將允許您在無鑰匙桌上插入,更新等。

如果你不太熟悉反向代碼優先,那麼去實體框架代碼優先找一個好的教程。然後,一旦你對此感到滿意,就去找一個關於反向代碼優先(Code First)和現有數據庫的代碼。然後回到這裏再看看我的重要建議。 :)

原來的答案

第一:正如其他人所說,最好的選擇是一個主鍵添加到表。句號。如果你能做到這一點,請不要再閱讀。

但是,如果你不能,或只是恨自己,有沒有辦法做到這一點,主鍵。基本上,我們要做的是對實體框架說謊,並告訴它有一個主鍵。

在我的情況下,我正在使用遺留系統(AS400上的最初平面文件移植到Access,然後移植到T-SQL)。所以我必須找到一個方法。這是我的解決方案。以下內容適用於我使用Entity Framework 6.0(NuGet截至撰寫本文時的最新版本)。

  1. 右鍵單擊解決方案資源管理器中的.edmx文件。選擇「打開方式...」,然後選擇「XML(文本)編輯器」。我們將在這裏手動編輯自動生成的代碼。

  2. 查找這樣一行:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">

  3. 從最終刪除store:Name="table_name"

  4. 變化store:Schema="whatever"Schema="whatever"

  5. 的外觀,線下,找到<DefiningQuery>標籤。它會有一個很大的選擇陳述。刪除標籤和它的內容。現在

  6. 你行應該是這個樣子:
    <EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />

  7. 我們還有別的改變。通過你的文件,去尋找這樣的:
    <EntityType Name="table_name">

  8. 最近你可能會看到一些評論文字警告你,它沒有一個主鍵識別,從而鍵已被推斷和定義是讀 - 僅表/視圖。您可以保留或刪除它。我刪了它。

  9. 以下是<Key>標籤。這是Entity Framework將用於插入/更新/刪除的內容。所以請確保你做到了這一點。該標籤中的屬性(或屬性)需要指明一個唯一可識別的行。例如,假設我知道我的表orders,雖然它沒有主鍵,但確保每個客戶只有一個訂單號。

所以我的樣子:

<EntityType Name="table_name"> 
       <Key> 
       <PropertyRef Name="order_numbers" /> 
       <PropertyRef Name="customer_name" /> 
       </Key> 

嚴重的是,不這樣做是錯誤的。假設即使不應該有重複,但有兩行以相同的訂單號和客戶名稱進入我的系統。 Whooops!這就是我不使用密鑰所得到的結果!所以我使用實體框架來刪除一個。因爲我知道重複是今天唯一的訂單,所以我這樣做:

var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today); 
myModel.orders.Remove(duplicateOrder); 

猜猜是什麼?我剛剛刪除了重複和原來的!這是因爲我告訴Entity Framework order_number/cutomer_name是我的主鍵。所以,當我告訴它刪除duplicateOrder,它在後臺做的是一樣的東西:

DELETE FROM orders 
WHERE order_number = (duplicateOrder's order number) 
AND customer_name = (duplicateOrder's customer name) 

有了這樣的警告......你現在應該好走!