We are using OrmLite to write records to a SQL DB. We recently added CSVHelper, a great NuGet for reading and writing CSVs and noticed that when we use the [Ignore] attribute in the CsvHelper.Configuration.Attributes namespace, OrmLite stopped writing those fields to the DB too. This is a major problem for us since we need to use the ignore attribute from the CSVHelper to achieve what we need there and had no thoughts it would impact what data is getting written by OrmLite. I would have expected the OrmLite code to only look for it’s own version of the Ignore attribute, but not one from a different namespace.
using ServiceStack;
[ApiMember(IsRequired = true, Description = "")]
[CsvHelper.Configuration.Attributes.Ignore]
Public List<string> MyStrings {get;set;}
Writing is just regular OrmLite Async writing and writes perfectly if I comment out the Ignore attribute.
In looking at the source code, I believe the issue is that you are calling:
var isIgnored = propertyInfo.HasAttributeNamed(nameof(IgnoreAttribute))
|| fieldDefinition.IsReference;
which matches on any attribute with that name instead of matching on specific type.
It was specifically added so you could use any Ignore attribute in your models and avoid the dependency to ServiceStack libraries in your POCOs. I’ll review it to see what impact it has.
I understand that desire, but including an Interfaces assembly in your POCO isn’t a disaster (it’s fairly common practice). Handcuffing the code so no other library can apply an Ignore attribute from it’s own namespace without harsh side effects is a steep price to pay. I don’t think its reasonable to ask anyone using OrmLite to not use any library that has their own Ignore attribute. If you feel strongly that an Ignore attribute with no SS reference must be supported then please rename it something more specific to OrmLite (e.g. OrmLiteIgnore or ServiceStack.Ignore) so you don’t overstep into other namespaces.
Not that we’re the only ones, but we spent the last 3 weeks implementing our CSV solution and if this isn’t fixed, we need to rip out CSVHelper and find another solution that doesn’t implement an Ignore attribute. Seems really odd to me to say that this is by design behavior.
When you see an [Ignore] attribute in a data model anyone reading the code is going to assume it means to ignore the field for persistence. I understand you’ve run into a naming conflict and are requesting we change the default behavior in the framework, but please keep in mind that this is the first report of any such conflict of this feature in over the 4 years it was added so I need to review this potentially breaking change. It’s only because this was never documented that we’re going to be able to remove it.
Looking back at the history it was added when we moved the [Ignore] attribute into a different assembly so the loose coupling was presumably to handle Ignore attributes defined in multiple assemblies. Given the change wasn’t in response to a specific use-case request it should have low impact so I’ve changed it to use a typed API in this commit.
As far as the comment of “When you see an [Ignore] attribute in a data model anyone reading the code is going to assume it means to ignore the field for persistence.” I would suggest that it isn’t correct to assume that ignore means the same thing to all persisters. Ignore is a fairly common attribute name and even if you could assume in many cases what people’s intent would be as far as DB persistence when that attribute is used, I don’t think it is correct to force it on 100% of cases. With the code as it was, there was no workaround option; we’d have to replace OrmLite altogether.
Specifically for the business problem you mentioned of loose coupling, might I suggest a much simpler solution (IMO more correct as well) which is as follows. Your previous solution asked that a POCO assembly create its own local version of the IgnoreAttribute to avoid a reference. You can still follow exactly the same pattern now, with the minor change that the local attribute class created belongs to the correct ServiceStack namespace - it will still resolve correctly with the new code you wrote, but will avoid over-reaching and assuming all Ignore attributes are intended for OrmLite. To quote my first development boss, “No need to cut off a hang nail with a hatchet.”