dimanche 18 décembre 2016

Data Attributes on EF POCO to Ignore Attributes When Exporting Object Values Violates SRP?

I am working with Entity Framework as my ORM for a project at work, and I need to be able to write only some of the values of each entity to an existing Excel template.

The data is required to be formatted as Excel Tables so that the end user can reference the information by using formulas like "=AVG(People_Table[Age])". (note, this is just a contrived example for a simplicity). There is also a requirement to export the values to PDF as well.

I've decide that reflection is the way to go to export the information in the least painful manner possible. The problem now, however, is I want to exclude certain properties from being written to the spreadsheet. And I also might want to write the properties in a certain order and specify a display format.

One way I could do this is with defining specific Data Attributes on the properties. I liked this answer on ignoring specific attributes: Exclude property from getType().GetProperties(). So a possible solution could be:

// class I want to export
public class PersonEntity {

    [SkipAttribute] // per solution in the referenced answer
    public int PersonId { get; set; }

    [SkipAttribute]
    public int ForeignKeyId { get; set; }

    [Display(Order = 3)]
    public int Age { get; set; }

    [Display(Name="First Name", Order = 1)]
    public string FirstName { get; set; }

    [Display(Name="Last Name", Order = 2)]
    public string LastName { get; set; }
}

The Problem I see with the above solution is that this entity class is now doing two things: One, proving a mapping between EF and the Database which is it's primary function, and two providing information on how to consume the class for exporting to Excel. I see this as getting messy and leading to confusion because it (possibly?) violates SRP.

An alternative solution that I see could be to create a separate set of classes that only contains the needed properties and to use this for exporting to Excel, and then using a tool like AutoMapper to map from EF Person to this class.

So, the export class would be:

public class PersonExportModel {

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int Age { get; set; }
}

And I would just use reflection to dump the values out to the specified format using ClosedXML or a PDF rendering library like ITextSharp.

Concern with the above solution is that this is going to end up with a lot of extra code just to ignore a few unwanted properties (mostly PK's, FK's, and some complex relationship properties). I am also at the issue any updates to the EF class, like removing a property, will require me to also go through the other classes and remove the corresponding properties.

So I'm stuck between either bloating my EF class to tell how it should be exported or creating other ExportModels that are tightly coupled to the EF class and would be a pain to update if the underlying model changes. And the whole mapping between classes is a real pain, which can be alleviated with AutoMapper. This comes with, however, it's own set of problems with obfuscated mapping and performance penalties. I could live with these "problems" if it means I do not have to manually map between the two classes.

I've thought about farming the work out to a SSRS but I need to ability to write the data to specific existing workbooks which I understand is not possible. I'd also need the ability to create named tables which also I understand is not possible out of the box with SSRS. I'd also need to create two reports because the Excel output would look much different than the PDF format. So even the SSRS would cause a lot of extra work.

Any suggestions on which solution might be best, or perhaps an alternative approach? The requirement of this project is in flux so I'm looking for a solution that will be as painless as possible to updates.





Aucun commentaire:

Enregistrer un commentaire