3

我有一個情況,我有一張我將要查詢的條目表,但在某些情況下,我會提供其他信息。例如,如果我有一個表people,我希望能夠按名稱進行搜索,但我也希望存儲一些座標並根據其位置進行搜索,但也會在對象模型中顯示該距離。所以,舉例來說,假設我people表看起來是這樣的:如何使用EF Code First表示選項計算欄?

PersonId int 
Name nvarchar(100) 
Address nvarchar(100) 
Latitude float(10,6) 
Longitude float(10,6) 

與實體類的定義是這樣的:

public class Person 
{ 
    public int PersonId { get; set; } 
    public sting Name { get; set; } 
    public float Latitude { get; set; } 
    public float Longitude { get; set; } 
} 

然後,我可以很容易地使用名字來找到一個人:

var people = from p in myDb.People where p.Name.Contains("joe"); 

現在,我已創建了用戶定義的函數,稱爲CalculateDistance,用於處理此距離計算。因此,我的SQL將如下所示:

String sql = "SELECT *, dbo.CalculateDistance(" + location.X + ", " + location.Y + ", Latitude, Longitude) AS Distance FROM people ORDER BY Distance 

如何在代碼中表示此代碼?我嘗試在類中添加如下屬性:

public virtual float Distance { get; set; } 

但是,名稱查詢失敗,因爲沒有「距離」列。我也嘗試擴展Person類:

public class PersonWithDistance: Person { 
    public float Distance { get; set; } 
} 

但是這樣會導致映射生成方式出現更多問題。

什麼是正確的方式來實現這樣的事情?我是否必須爲距離查詢的結果創建一個完全獨立的單獨的類?

回答

1

嗯,我結束了創建一個PersonResult類,它包含一個IdDistance和一個Person對象,像這樣:

public class PersonResult { 
    [Key] 
    public int PersonId { get; set; } 
    public double Distance { get; set; } 
    public virtual Person Person { get; set; } 
} 

我填充,從這樣的存儲過程:

var results = myDb.PersonResults.SqlQuery("EXEC PeopleByDistance " + lat + ", " + lng); 

並遍歷結果來填充Person對象:

foreach (PersonResultresult in results) 
{ 
    result.Person = myDb.People.Where(p => p.PersonId == result.PersonId).FirstOrDefault(); 
} 

這似乎運作良好。雖然我不確定這是處理它的最好方法。

+4

我使用計算列(也因爲我想排序)。你可以添加'[DatabaseGenerated(DatabaseGeneratedOption.Computed)]',EF不會爲這個列打擾你。在Code First中,它甚至會爲你創建列,然後使用EF Migrations進行自定義遷移列,添加函數,並重新添加列'ADD COLUMN Foo AS([dbo]。[CalculateDistance]([Column1],[Column2]))' – kamranicus 2012-03-17 22:57:07

+0

@subkamran你應該使這個答案 – mcalex 2014-08-21 03:41:18

4

這不是很好的設計。您應該將距離作爲Person或某個助手類的方法,並且在應用程序中計算距離而不是數據庫中的距離。它也需要將位置轉移給該人。

無論如何,如果你想添加一些未映射到數據庫中的列的屬性,你必須從映射中排除它。

[NotMapped] 
public float Distance { get; set; } 

或流暢API:這可以通過屬性來完成

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    base.OnModelCreating(modelBuilder); 

    modelBuilder.Entity<Person>().Ignore(p => p.Distance); 
} 
+2

從應用程序執行它的問題是,我想按距離排序。如果我想要顯示距離給定位置最近的10個人,那麼在代碼中執行操作時需要從數據庫中加載每條記錄。我仍然對如何實際獲得填充在我的對象中的「距離」值感到困惑。如果我只是使用SqlQuery(「select *,dbo.CalculateDistance(...」),我收到一條消息,指出「沒有映射從對象類型<> f__AnonymousType0'存在」 – 2011-03-14 18:45:48