-
Notifications
You must be signed in to change notification settings - Fork 0
Model
Use DbTableAttribute for mapping classes and tables.
If the table name is omitted, the table name will be the class name converted to snake case.
[DbTable("blogs")]
public class Blog
{
}
Use DbColumnAttribute to map properties and columns.
Column type name is required.
If the column name is omitted, the column name will be the property name converted to snake case.
Specify primary key, autonumber, and unique key properties as required.
[DbTable("blogs")]
public class Blog
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int BlogId { get; set; }
}
DbParentRelationColumnAttribute can represent a join condition with objects that have a relationship of 0 or 1.
DbParentRelationColumnAttribute specifies the type name, its own column name, and the destination "property" name.
DbParentRelationColumnAttribute is AllowMultiple.
If the column name is omitted, the property name + "id" will be treated as the column name.
Normally it is a 1:1 relationship, but in the case of a nullable type, it is a 1:0 or 1 relationship.
[DbTable("posts")]
public class Post
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int? PostId { get; set; }
[DbParentRelationColumn("bigint", nameof(Post.Blog.BlogId))]
public Blog Blog { get; set; } = null!;
}
Notice that table 'posts' has columns 'post_id', 'blog_id', but no BlogId property. The column "blog_id" is mapped to the Blog property.
[DbTable("posts")]
public class Post
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int? PostId { get; set; }
// not good
[DbColumn("bigint")]
public int BlogId { get; set; }
}
To express a relationship of 0 or N, specify DbChildrenAttribute.
The type of the property to which attributes should be attached should be a list type such as IList type, which allows only specific types to be registered.
Different classes must have properties that refer to their parents.
[DbTable("blogs")]
public class Blog
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int BlogId { get; set; }
// Defining being a child
[DbChildren]
public List<Post> Posts { get; } = new();
}
[DbTable("posts")]
public class Post
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int? PostId { get; set; }
// Defines the conditions for joining with the parent
[DbParentRelationColumn("bigint", nameof(Post.Blog.BlogId))]
public Blog Blog { get; set; } = null!;
}
For example, if there is an instance called blog, the model must ensure that blog.Posts[0].Blog.Equal(blog).
To ensure this relationship, we recommend using an ObservableCollection.
Using ObservableCollection, it can be expressed as follows.
// vanilla
[DbTable("blogs")]
public class Blog
{
[DbChildren]
public DirtyCheckableCollection<Post> Posts { get; } = new();
public Blog()
{
Posts.CollectionChanged += Posts_CollectionChanged;
}
private void Posts_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
if (e.NewItems == null) return;
foreach (Post item in e.NewItems)
{
item.Blog = this;
}
}
}
}
It is difficult to write the above code without missing anything, so we recommend using PropertyBind. If you use the same library, the above code can be written as follows.
// use PropertyBind
[GeneratePropertyBind(nameof(Posts), nameof(Post.Blog))]
[DbTable("blogs")]
public partial class Blog
{
[DbChildren]
public DirtyCheckableCollection<Post> Posts { get; }
}
Although not required, it is also possible to define an index using DbIndexAttribute. Please specify the property name you want to index.
[DbTable("blogs")]
[DbIndex(true, nameof(Url))]
public partial class Blog
{
[DbColumn("text")]
public string Url { get; set; } = string.Empty;
}
You can obtain a definition class by passing a type with various attributes to the Create method of the DefinitionBuilder class.Please register the table mapping definition in RedOrb using the ObjectRelationMapper.AddTypeHandler method.
using RedOrb.Attributes;
var def = DefinitionBuilder.Create<Blog>();
ObjectRelationMapper.AddTypeHandler(def);
NOTE: Please register only once in the application.
DDL can be generated from definition classes. However, this function is called internally within the framework, so there is usually no need to call it.
var createTable = def.ToCreateTableCommandText();
var createIndex = def.ToCreateIndexCommandTexts();
create table if not exists blogs (
blog_id serial8 not null,
url text not null,
primary key(blog_id)
)
;
create unique index if not exists i1_blogs on blogs (url)
;
using PropertyBind;
using RedOrb;
using RedOrb.Attributes;
[GeneratePropertyBind(nameof(Posts), nameof(Post.Blog))]
[DbTable("blogs")]
[DbIndex(true, nameof(Url))]
public partial class Blog
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int BlogId { get; set; }
[DbColumn("text")]
public string Url { get; set; } = string.Empty;
[DbChildren]
public DirtyCheckableCollection<Post> Posts { get; }
}
[DbTable("posts")]
public partial class Post
{
[DbColumn("serial8", IsAutoNumber = true, IsPrimaryKey = true)]
public int PostId { get; set; }
[DbParentRelationColumn("bigint", nameof(Post.Blog.BlogId))]
public Blog Blog { get; set; } = null!;
[DbColumn("text")]
public string Title { get; set; } = string.Empty;
[DbColumn("text")]
public string Content { get; set; } = string.Empty;
}