2017-01-21 125 views
2

我想將BL從DAL解耦。特別是我想要主鍵保護(我不希望我的業務用戶修改Item.Id)。如何在解耦數據層中設置主鍵

在我的數據層(讓我們想象它是自動生成的主鍵的簡單的SQL表),我嘗試插入項目和更新item.Id. 當然,我不能因爲它是受保護的財產。

有沒有辦法做到這一點,而不使用反射? (我的意思是,也許我的架構是錯誤的...)

BusinessLayer:

public class Item 
{ 
    public int Id { get; protected set; } 

    public string Name { get; set; } 
} 

public interface IRepository<Item> 
{ 
    void Insert(Item item); 

    //and other CRUD operations 
} 

數據層(使用的EntityFramework與SQLSERVER):

public class EfRepository : IRepository<Item> 
{ 
    EfContext ctx;  
    public void Insert(Item item) 
    {  
     //EfContext uses its ItemEntity, so I have to map Item to EntityItem 
     var mapped = AutoMapper.Map<Item, EntityItem>(item); 
     ctx.Items.Add(mapped); 
     //after this operation EF will set primary key to mapped object 
     //and now I need to set this to primary key to my business 
     //domain object. 
     item.Id = ?? // can't set protected property!!! 
    } 
} 
+0

您正在使用的數據庫? –

+0

,如果你使用的是SQL服務器,那麼你可以把它放在塊本身不需要做任何更多的 –

+0

創建表測試 ( ID INT標識(1,1)主鍵, 名稱爲varchar(100) ) –

回答

1

爲了保護您的邏輯,防止意外修改Id您可以使用「屬性注塑模式」 :

public class Item 
{ 
    public Item() 
    { 
     _id = -1; 
    } 

    public int Id 
    { 
     get 
     { 
      return _id; 
     } 

     set 
     { 
      if (_id != -1) 
      { 
       throw new OperationException("Item.Id has already been set"); 
      } 

      _id = value; 
     } 
    } 

    public string Name { get; set; } 
} 
+1

它需要改變Item.Id公衆,但應該工作。 –

+1

是的,但您的意圖是避免業務用戶修改Item.Id_,而不是?這是非常簡單的解決方案。 ;) –

1

你應該在數據庫中實現這一點。你如何做這取決於你正在使用哪個數據庫。

如果您需要專門通過代碼設置一些其他的ID,我會建議專門增加一個屬性,用於和讓你的數據庫還是生成主鍵。

例如,你可以用小巧玲瓏來調用存儲過程,將你想插入(和任何密鑰生成)。

1

,如果你使用的是SQL服務器,那麼你可以把它放在塊本身不需要做任何事情更

create table test 
(
Id int Identity(1,1) primary key , 
    Name varchar(100) 
) 

你也可以改變現有INT列是身份,我的意見

如前所述以及。使用ALTER TABLE SQL命令

0

只要你正在使用的主鍵自動生成的順序整數,你將不得不與保護數據的幾個問題。您必須將密鑰從服務器傳遞到客戶端,因此當用戶更新數據時,您可以找到關聯的記錄。惡意用戶可以使用不同的工具更改PK並通過簡單地更改主鍵的值來訪問不同的記錄,因爲可以輕鬆猜測其他記錄的PK值。當然你知道這一切。

此問題的行業標準解決方案是使用不易猜測的密鑰(不是連續的整數值)。如果您使用SQL Server作爲數據庫,那麼可以添加一個新列到您的表中,並將其類型定義爲GUID並將其用作PK。 GUID值將被服務器自動分配,它不是連續的,並且猜測其他值非常困難。我不熟悉其他數據庫引擎,但總之,解決方案是使用GUID。

這裏是如何聲明的列和表(從這個MSDN文章複製:https://technet.microsoft.com/en-us/library/ms190215(v=sql.105).aspx)添加行

CREATE TABLE MyUniqueTable 
    (UniqueColumn UNIQUEIDENTIFIER  DEFAULT NEWID(), 
    Characters  VARCHAR(10)) 
GO 
INSERT INTO MyUniqueTable(Characters) VALUES ('abc') 
INSERT INTO MyUniqueTable VALUES (NEWID(), 'def') 
+0

我想過GUID,但我嘗試設計我的應用程序,以便業務邏輯中的用戶只能讀取主鍵(也許這是錯誤的設計)。主鍵只能在數據層設置。 –

+0

GUID可以是主鍵。沒有規則說PK必須被定義爲一個整數。主鍵是唯一標識每條記錄的關鍵字。由於GUID是獨一無二的,它可以被用來作爲主鍵也 – Sparrow