oysteinkrog / SQLite.Net-PCL

Simple, powerful, cross-platform SQLite client and ORM - Updated version with PCL support
MIT License
353 stars 162 forks source link

Allowing custom attributes to determine Primary Key, Auto Increment, etc. #298

Closed eclipsed4utoo closed 8 years ago

eclipsed4utoo commented 8 years ago

These changes allow for attributes(and other logic) from outside of the library to determine whether a column is a Primary Key, Auto Incremented, Indexed, etc.

Reason: I am writing data contracts that I want to be storage agnostic, meaning that I don't want to clutter my data contracts with attributes from many different storage technologies. These could be used by anybody in my company against any data storage technology(json or xml files, SQLite, EntityFramework, etc.). We have this working for the most part for EntityFramework and other storage techs. I am currently implementing storage in our Xamarin application and there are properties I want to ignore from the SQLite database.

For instance, let's say I have an interface and an implementation. Currently, if I wanted to ignore the EmployeeID property, I have to put in ignore attributes like below...

public interface IDataItem
{
    int ID { get; set; }
}

public class DataItem : IDataItem
{
    public int ID { get; set; }
}

public class Employee : DataItem
{
    [JsonIgnore]
    [XmlIgnore]
    [SQLite.Net.Ignore]
    // other "ignore" attributes from other storage providers(ie. Entity Framework, etc.)
    // since we already have ID, we don't need both columns in a database/file since they
    //   both refer to the same value
    public int EmployeeID 
    {
        get { return base.ID; }
        set { base.ID = value }
    }
}

I want to be able to do something like this...

public class MyIgnoreAttibute : Attribute
{

}

public class Employee : DataItem
{
    [MyIgnoreAttribute]
    public int EmployeeID { get; set; }
}

where we can use MyIgnoreAttribute to ignore the column in SQLite without having to have a reference to SQLite.

This is what I have accomplished with my changes. By providing an instance of IColumnInformationProvider, an outside class can determine the information about the column. So for my case, my provider would look like...

public MyColumnInfoProvider : IColumnInformationProvider
{
    // ... other interface methods implemented

    public bool IsIgnored(PropertyInfo p)
    {
        return p.IsDefined(typeof (MyIgnoreAttribute), true);
    }
}

//... somewhere in my code...
var sqlConnection = new SQLiteConnection(....);
sqlConnection.ColumnInformationProvider = new MyColumnInfoProvider();

The changes made to the library are backwards compatible. Setting this property is not required. If an instance is not provided, an instance of the DefaultColumnInformationProvider class will be created and used. This default instance does exactly what the code previously did. So not giving a provider will make the library work exactly the same as before.

oysteinkrog commented 8 years ago

This looks nice and I like the idea. I'm currently on vacation but I will take a look next week when I'm back :)

eclipsed4utoo commented 8 years ago

Thanks @oysteinkrog . I just noticed that I made the changes to the SQLite.Net solution and NOT the SQLite.Net.OSS solution. Is that going to be a problem?

eclipsed4utoo commented 8 years ago

@oysteinkrog will you be able to take a look at the pull request this week? Thanks

oysteinkrog commented 8 years ago

Sorry for the delays.

This looks good, my only complaint is that you did not use the same formatting as the rest of the code (tabs vs whitespace indentation etc), but I'll fix that.

Thank you :)

eclipsed4utoo commented 8 years ago

Awesome. Thanks. Is there a threshold that needs to be hit before releasing a new release on nuget? The last release was in November :(. I'm just looking forward to stop using my custom built DLL and back to using the nuget packages.

eclipsed4utoo commented 8 years ago

Would it be possible to get a new nuget package release? I want to switch our code back to using the nuget package instead of the built DLL we are using now(since the nuget package doesn't currently have the changes from this pull request). Thanks.

eclipsed4utoo commented 8 years ago

Is there any chance a new nuget package can be built and published? We would like to avoid using our locally built DLLs as we are reliant on the changes in this pull request. Thanks.