Можно ли настроить linq2db так, чтобы не писать явно внешний ключ в классе Order:
[Table("Partners")]
class Partner
{
[PrimaryKey, Identity]
public long ID { get; set; }
[Column]
public string Name { get; set; }
}
[Table("Orders")]
class Order
{
[PrimaryKey, Identity]
public long ID { get; set; }
[Column]
public string Number { get; set; }
[Association(ThisKey = "Partner", OtherKey = "ID")]
public Partner Partner { get; set; }
}
И при этом было доступно примерно такое:
var query = db.GetTable<Order>().Select(_=>_.Partner.Name);
var list = query.ToList();
Здравствуйте, Naf2000, Вы писали:
N>Имеется простейшая схема базы N>Image: OpderPartner.PNG N>Можно ли настроить linq2db так, чтобы не писать явно внешний ключ в классе Order:
Можно через extensions, только получится не свойство, а метод.
public static class AssociationExtensions
{
[Association(ThisKey = "Partner", OtherKey = "ID")]
public static Partner Partner(this Order order)
{
throw new InvalidOperationException("Used only as Association helper");
}
}
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Naf2000, Вы писали:
N>>Имеется простейшая схема базы N>>Image: OpderPartner.PNG N>>Можно ли настроить linq2db так, чтобы не писать явно внешний ключ в классе Order:
IT>Можно через extensions, только получится не свойство, а метод.
IT>
IT>public static class AssociationExtensions
IT>{
IT> [Association(ThisKey = "Partner", OtherKey = "ID")]
IT> public static Partner Partner(this Order order)
IT> {
IT> throw new InvalidOperationException("Used only as Association helper");
IT> }
IT>}
IT>
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Naf2000, Вы писали:
N>>Имеется простейшая схема базы N>>Image: OpderPartner.PNG N>>Можно ли настроить linq2db так, чтобы не писать явно внешний ключ в классе Order:
IT>Можно через extensions, только получится не свойство, а метод.
IT>
IT>public static class AssociationExtensions
IT>{
IT> [Association(ThisKey = "Partner", OtherKey = "ID")]
IT> public static Partner Partner(this Order order)
IT> {
IT> throw new InvalidOperationException("Used only as Association helper");
IT> }
IT>}
IT>
Что-то не вышло: LinqToDB.Linq.LinqException: "Association key 'Partner' not found for type 'ConsoleApp21.Order."
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Naf2000, Вы писали:
N>>Что-то не вышло: LinqToDB.Linq.LinqException: "Association key 'Partner' not found for type 'ConsoleApp21.Order."
IT>А раньше выходило?
В случае свойства выходило так:
Необработанное исключение типа "System.InvalidOperationException" в linq2db.dll
The binary operator Equal is not defined for the types 'ConsoleApp21.Partner' and 'System.Int64'.
Здравствуйте, Naf2000, Вы писали:
N>Здравствуйте, IT, Вы писали:
IT>>Здравствуйте, Naf2000, Вы писали:
N>>>Что-то не вышло: LinqToDB.Linq.LinqException: "Association key 'Partner' not found for type 'ConsoleApp21.Order."
IT>>А раньше выходило?
N>В случае свойства выходило так:
N>Необработанное исключение типа "System.InvalidOperationException" в linq2db.dll N>The binary operator Equal is not defined for the types 'ConsoleApp21.Partner' and 'System.Int64'.
Partner — ассоциация, а надо ссылка на поле ключа.
Здравствуйте, Mace Windu, Вы писали:
MW>Здравствуйте, Naf2000, Вы писали:
N>>Здравствуйте, IT, Вы писали:
IT>>>Здравствуйте, Naf2000, Вы писали:
N>>>>Что-то не вышло: LinqToDB.Linq.LinqException: "Association key 'Partner' not found for type 'ConsoleApp21.Order."
IT>>>А раньше выходило?
N>>В случае свойства выходило так:
N>>Необработанное исключение типа "System.InvalidOperationException" в linq2db.dll N>>The binary operator Equal is not defined for the types 'ConsoleApp21.Partner' and 'System.Int64'.
MW>Partner — ассоциация, а надо ссылка на поле ключа.
MW>
N>сомневаюсь, в таблице Orders поле ключа называется "Partner" все-таки
Тогда его забыли объявить
[Table("Orders")]
class Order
{
[PrimaryKey, Identity]
public long ID { get; set; }
[Column]
public string Number { get; set; }
[Association(ThisKey = "PartnerId", OtherKey = "ID")]
public Partner Partner { get; set; }
// например так
[Column("Partner")]
public long? PartnerId { get; set; }
}
Здравствуйте, Naf2000, Вы писали:
IT>>А раньше выходило? N>В случае свойства выходило так: N>Необработанное исключение типа "System.InvalidOperationException" в linq2db.dll N>The binary operator Equal is not defined for the types 'ConsoleApp21.Partner' and 'System.Int64'.
Оно не может работать в принципе, потому как ThisKey задан неверно. Я поначалу просто не обратил внимания и тупо скопировал код.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Naf2000, Вы писали:
N>>Казалось бы примерно с этого и начиналась ветка обсуждения. Как не объявлять
НС>А зачем?
Причин несколько и они в какой-то мере взаимосвязаны:
1. Зачем иметь PartnerID как отдельное свойство, если сам Partner содержит эти данные в ID?
2. PartnerID низкоуровневый термин (попросту число) чем Partner. Зачем им оперировать, если можно обращаться с объектами из модели? К тому же это небезопасно. Запросто можно написать PartnerID==OrderID что семантически неверно. Написать Partner==Order не выйдет.
3. Может произойти коллизия не консистентности, когда PartnerID!=Partner.ID
Здравствуйте, Naf2000, Вы писали:
N>1. Зачем иметь PartnerID как отдельное свойство, если сам Partner содержит эти данные в ID?
С точки зрения реляционной модели это разные вещи. Ну и философия linq2db — не маскировать природу данных. Поэтому идея прятать реально существующее поле — так себе.
N>2. PartnerID низкоуровневый термин (попросту число) чем Partner.
Да. В этом суть l2db — lightweight ORM. Если подход не устраивает — лучше выбрать другой инструмент, более тяжеловесный.
N>3. Может произойти коллизия не консистентности, когда PartnerID!=Partner.ID
Не может, если сделать свойство Partner readonly и выбрасывать исключение при попытке к нему обратиться.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Здравствуйте, Naf2000, Вы писали:
N>>1. Зачем иметь PartnerID как отдельное свойство, если сам Partner содержит эти данные в ID?
НС>С точки зрения реляционной модели это разные вещи. Ну и философия linq2db — не маскировать природу данных. Поэтому идея прятать реально существующее поле — так себе.
N>>2. PartnerID низкоуровневый термин (попросту число) чем Partner.
НС>Да. В этом суть l2db — lightweight ORM. Если подход не устраивает — лучше выбрать другой инструмент, более тяжеловесный.
N>>3. Может произойти коллизия не консистентности, когда PartnerID!=Partner.ID
НС>Не может, если сделать свойство Partner readonly и выбрасывать исключение при попытке к нему обратиться.
И все таки удалось:
[Table("Partners")]
public class Partner
{
[PrimaryKey, Identity]
public long ID { get; set; }
[Column]
public string Name { get; set; }
}
[Table("Orders")]
[Column(Name="Partner",MemberName="Partner.ID")]
public class Order
{
[PrimaryKey, Identity]
public long ID { get; set; }
[Column]
public string Number { get; set; }
private static Expression<Func<Order, IDataContext, IQueryable<Partner>>> PartnerImpl => (_, db) => db.GetTable<Partner>().Where(s => s.ID == _.Partner.ID);
[Association(QueryExpressionMethod = nameof(Order.PartnerImpl))]
public Partner Partner { get; set; }
}