Как мне представить опциональный вычисляемый столбец с EF Code First? - PullRequest
3 голосов
/ 14 марта 2011

У меня есть ситуация, когда у меня есть таблица записей, к которой я буду запрашивать, но в некоторых случаях у меня будет дополнительная информация.

Например, если у меня есть таблица people, я хочу иметь возможность поиска по имени, но я также хочу сохранить некоторые координаты и поиск на основе их местоположения, но также выставить это расстояние в модели объекта , Например, предположим, что моя таблица people выглядит примерно так:

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; }

Но тогда запросы на имя не будут выполнены, поскольку столбец Distance отсутствует. Я также пытался расширить класс Person:

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

Но это вызвало еще больше проблем с тем, как генерируются отображения.

Как правильно реализовать что-то подобное? Нужно ли создавать отдельный отдельный класс для результатов запроса расстояния?

Ответы [ 2 ]

4 голосов
/ 14 марта 2011

Это не очень хороший дизайн. Вы должны использовать расстояние в качестве метода Person или некоторого вспомогательного класса и вычислять расстояние в вашем приложении, а не в базе данных. Это также потребовало бы передачи местоположения человеку.

В любом случае, если вы хотите добавить какое-либо свойство, которое не отображается в столбце базы данных, вы должны исключить его из отображения. Это можно сделать по атрибуту:

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

или по API:

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

    modelBuilder.Entity<Person>().Ignore(p => p.Distance);
}
1 голос
/ 15 марта 2011

В итоге я создал класс PersonResult, который содержит Id, Distance и объект 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();
}

Кажется, это работает хорошо.Хотя я не уверен, что это лучший способ справиться с этим.

...