Dynamic "tables"
See original GitHub issueI have an application where administrators can design the database using a UI and this part of the application is handled without linq2db, meaning, it already works.
If some developer developed a typed entity, it works fine with linq2db but what if there is no typed entity?
Imagine I have a table that linq2db has no idea about. I would like to be able to query that table using the dynamic columns store feature.
class DynamicTable
{
[PrimaryKey, Identity]
public long Id { get; set; }
[DynamicColumnsStore]
public IDictionary<string, object> ExtendedProperties { get; set; }
}
That requires several things.
Entity
method needs atableName
parameter or some unique value that we can use when building schema for multipleDynamicTable
instances, because there can be more than one with each having different dynamic columns.
// Current:
Entity<DynamicTable>()
// Hoped:
Entity<DynamicTable>("Table1").Property... // (column1, column2)
Entity<DynamicTable>("Table2").Property... // (otherColumn1, otherColumn2)
DataConnection.GetTable<T>
needs another overload there we can pass it the exactDynamicTable
instance we want to construct.
// Current:
cnn.GetTable<DynamicTable>();
// Hoped:
cnn.GetTable<DynamicTable>("Table1")
cnn.GetTable<DynamicTable>("Table2")
- Use fluent mapper to define dynamic columns in advance. linq2db doesn’t know those but we do. There is one problem here,
Sql.Property
method is generic. It would be really helpful if there was a non-generic variation of it. So that we don’t have to use reflection.
// Current:
Property(x => Sql.Property<string>(x, "DynColumn"))
// Hoped:
Property(x => Sql.Property(typeof(string), "DynColumn")) // Why do we need "x"?
Finally, the easiest of all of these is being able to implement a custom IDynamicColumnMetadataProvider
, something similar to below. That would eliminate all of the requirements above (except GetTable<T>(“name”)). We wouldn’t need to register dynamic columns in advance. You could easily ask us to provide you the list/schema of dynamic columns the first time that table is requested from the connection. I said “except GetTable<T>(name)” because the name
parameter is used in the IDynamicColumnMetadataProvider
.
class DynamicColumnMetadata
{
public Type Type { get; set; }
public Type Name { get; set; }
public Attribute[] Attributes { get; set; }
}
interface IDynamicColumnMetadataProvider
{
DynamicColumnMetadata[] GetDynamicColumns(string tableName);
}
class DynamicColumnMetadataProvider : IDynamicColumnMetadataProvider
{
public DynamicColumnMetadata[] GetDynamicColumns(string tableName)
{
if (tableName == "Table1")
{
// return dynamic columns for Table1
}
else if (tableName == "Table2")
{
// return dynamic columns for Table2
}
}
}
// On initialize
var ms = new MappingSchema
{
MetadataReader = new CustomMetadataReader(),
DynamicColumnsMetadataReader = new CustomDynamicColumnsMetadataReader()
}
cnn.AddMappingSchema(ms);
What is your opinion on this use case? Is there a better approach that I am not aware of?
Thank you in advance!
Issue Analytics
- State:
- Created 5 years ago
- Comments:31 (27 by maintainers)
Some questions/suggestions
or you cannot assign each table own type?
take into account this issue #1274 and don’t reuse GetTable result