Mali is a Bi-Directional Type-Relational Mapper for F#. In other words, it enables you to convert F# record types to relational database tables and vice versa, while also providing a convenient interface to relational databases to use within your code.
open System
open Mali.Util.Types
open Mali.Mapping
type Member =
{[<PrimaryKey>]
id: int;
name: string;
[<Unique>]
[<NonNullable>]
email: string;
[<OneToMany>]
posts: Post list;}
and Post =
{[<PrimaryKey>]
id: int;
content: string;
timeStamp: DateTime;
[<Ref(Parent="posts")>]
poster: Member;}
[<EntryPoint>]
let main _ =
fromType typeof<Member>
|> List.map (createTable)
|> List.iter (printfn "%s")
Console.ReadLine()
|> ignore
0
At this time, Mali does not use any dependencies besides the .NET Core 2 platform itself. Once you install .NET Core, it should be easy to build and run the project. If you're using Windows and Visual Studio, you should have the .NET Core tools installed along with Visual F#. Meanwhile if you're building Mali on any other platform (or using an editor on Windows that isn't Visual Studio), just ensure that F# and the .NET Core SDK are installed. Once you've done so, you can run the existing demo with
$ cd Playground
$ dotnet run
CREATE TABLE Post (id INT PRIMARY KEY, content TEXT , timeStamp TIMESTAMP , poster INT REFERENCES Member(id) )
CREATE TABLE Member (id INT PRIMARY KEY, name TEXT , email TEXT UNIQUE NOT NULL)
Thank you so much for contributing to Mali! While pull requests are welcome and encouraged, there are several other ways in which you can contribute to Mali's development, namely by opening or commenting on issues in order to:
- Request features
- Report bugs
- Give feedback regarding how an issue is being handled
- Ask for better documentation on a specific part of the codebase
Code quality is a priority, but my code is not perfect nor do I expect yours to be. However, when submitting pull requests keep these things in mind:
- Ensure that your code is well commented, and that only descriptions are XML Doc'd (i.e. triple-slashed)
- Try to comply with section 3 of the F# Component Design Guidelines
- If you can test your own code, great! If not, it might get pushed to the testing branch before the master branch until it's been effectively tested
Mali is bi-directional. This means that it supports two "modes" of use. One covers the situation in which the user has modelled their data in native F# types and wants to map these types to a relational database. The other covers the situation in which the user already has a relational database set up with their data modelled the way they'd like it to be, and wants to map these tables to native F# types.
C#'s Entity Framework calls the first situation a "code-first" approach, and the other a "database-first" approach.
Many popular Object Oriented languages have tools within their ecosystem called ORMs. ORM stands for Object-Relational Mapping, and is a technique that converts objects in an OO language to records in a relational database. Type-Relational Mapping is very similar, but maps functional record types to database tables as opposed to mapping OO classes.