如何为表和视图使用相同的DTO外键关系

时间:2018-01-07 20:30:06

标签: c# servicestack ormlite-servicestack

我使用ORMLite并且我在发票DTO和发票行DTO之间定义了外键关系:

public interface IDto<PKType> where PKType : struct
{
    [Required(ErrorMessage = "Id is required")]
    PKType Id { get; set; }
}

[Ss.Alias("Invoices")]    
public class InvoiceDto : AuditedDto, IAuditedDto, IDto<Guid>
{
    [Required]
    public Guid VendorId { get; set; }

    [Ss.Reference]
    public List<InvoiceLineDto> InvoiceLines { get; set; }
}

[Ss.Alias("InvoiceLines")]
public class InvoiceLineDto : AuditedDto, IAuditedDto, IDto<Guid>
{
    [Required]
    public string Item { get; set; }

    [Required]
    public int Qty { get; set; }

    [Required]
    public decimal UnitPrice { get; set; }

    [Ss.ForeignKey(typeof(InvoiceDto))]
    public Guid InvoiceId { get; set; }
}

现在,我已在我的发票中定义了一个视图,该视图返回相同的数据,但包含发票状态:

[Ss.Alias("InvoiceStatus")]    
public class InvoiceStatusDto : InvoiceDto
{
    public int Status { get; set; }
}

但是当我查询InvoiceStatus视图时,这会给出System.ArgumentException: Cant find 'InvoiceStatusId' Property on Type 'InvoiceLineDto'。我不确定如何解决这个与InvoiceLineDto重复的问题,以便定义外键关系。是否有某种方法可以使用代码而不是注释来处理这种情况?

1 个答案:

答案 0 :(得分:3)

OrmLite foreign keyreferences attributes relies on naming conventions。问题是InvoiceLines表维护Invoices表的外键而不是InvoiceStatus表。

你试图在你的数据模型中过度使用继承,这可能是对DRY的追求。 OrmLite的POCO数据模型应该将1:1映射到RDBMS表,使用多级继承表明这不是这种情况,或者如果底层RDBMS有不必要的表爆炸。

虽然在没有导致耦合冲突的情况下干掉您的实现逻辑应该是一个目标,但这不适用于您的POCO或模式定义......

滥用继承隐藏属性

Hiding properties isn't duplicating code,它明确表达了意图。属性是声明性的,隐藏它们只会使您更难以阅读和推理您的代码,这需要打开多个源文件,并减轻开发人员阅读代码的负担,并通过强制他们合并和构建模式来增加他们的认知负载从他们头脑中的多个源文件,而不是他们能够查看具有显式列出的表的所有属性的单个源文件。

数据模型中的多级继承是滥用继承,我怀疑它是紧耦合问题和糟糕的RDBMS设计的原因。我不知道您需要一个完全独立的InvoiceStatus表,而不是维护一个包含Invoice字段的Status表。

表结构的其他问题是Dto后缀,表示这些是DTO而不是数据模型。虽然它perfectly reasonable to reuse OrmLite's Data Model classes as DTOs后缀为Dto,但您建议您与数据模型分开维护单独的特定目的DTO类(即序列化)。但是,此示例将[ForeignKey]属性添加到DTO类,而不是将它们添加到数据模型类中。

另一个命名问题是,您的某些RDBMS表使用不一致的复数命名约定,[Ss.Alias("InvoiceLines")]为复数,而[Ss.Alias("InvoiceStatus")]则不是。