Skip to content

Commit

Permalink
json schema add readonly datatype property, fix #40
Browse files Browse the repository at this point in the history
  • Loading branch information
voronov-maxim committed Feb 26, 2020
1 parent 208a045 commit e507855
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 19 deletions.
18 changes: 18 additions & 0 deletions source/OdataToEntity.Ef6/OeEf6EdmModelMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,24 @@ public override PropertyInfo[] GetPrincipalToDependentWithoutDependent(PropertyI

return null;
}
private static StoreGeneratedPattern GetStoreGeneratedPattern(EdmProperty property)
{
if (property.MetadataProperties.TryGetValue("http://schemas.microsoft.com/ado/2009/02/edm/annotation:StoreGeneratedPattern", false, out MetadataProperty item))
return (StoreGeneratedPattern)Enum.Parse(typeof(StoreGeneratedPattern), (String)item.Value);
return StoreGeneratedPattern.None;
}
public override bool IsDatabaseGenerated(PropertyInfo propertyInfo)
{
foreach (EntityType efEntityType in GetEntityTypes(propertyInfo))
{
EdmProperty efProperty = efEntityType.DeclaredProperties.FirstOrDefault(p => p.Name == propertyInfo.Name);
if (efProperty != null)
return GetStoreGeneratedPattern(efProperty) != StoreGeneratedPattern.None;
}

throw new InvalidOperationException("property " + propertyInfo.Name + " not found");

}
public override bool IsKey(PropertyInfo propertyInfo)
{
foreach (EntityType efEntityType in GetEntityTypes(propertyInfo))
Expand Down
11 changes: 11 additions & 0 deletions source/OdataToEntity.EfCore/OeEfCoreEdmModelMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,17 @@ private PropertyInfo GetPropertyInfo(IPropertyBase efProperty)

return efProperty.PropertyInfo;
}
public override bool IsDatabaseGenerated(PropertyInfo propertyInfo)
{
foreach (IEntityType efEntityType in GetEntityTypes(propertyInfo))
{
IProperty efProperty = efEntityType.FindProperty(propertyInfo.Name);
if (efProperty != null)
return efProperty.ValueGenerated != ValueGenerated.Never;
}

throw new InvalidOperationException("property " + propertyInfo.Name + " not found");
}
public override bool IsKey(PropertyInfo propertyInfo)
{
foreach (IEntityType efEntityType in GetEntityTypes(propertyInfo))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ public override PropertyInfo[] GetPrincipalToDependentWithoutDependent(PropertyI
}
throw new InvalidOperationException("Pricipal structurlal property not found for principal navigation " + principalNavigation.Name);
}
public override bool IsDatabaseGenerated(PropertyInfo propertyInfo)
{
return propertyInfo.GetCustomAttribute(typeof(IdentityAttribute)) != null;
}
public override bool IsKey(PropertyInfo propertyInfo) => propertyInfo.GetCustomAttribute(typeof(PrimaryKeyAttribute)) != null;
public override bool IsNotMapped(PropertyInfo propertyInfo)
{
Expand Down
37 changes: 24 additions & 13 deletions source/OdataToEntity/ModelBuilder/EntityTypeInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OData.Edm.Vocabularies.V1;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -75,7 +77,26 @@ private void AddKeys()
}
EdmType.AddKeys(keys.OrderBy(p => p.Item2).Select(p => p.Item1));
}
private void BuildProperty(Dictionary<Type, EntityTypeInfo> entityTypes,
public void BuildStructuralProperties(EdmModel edmModel, Dictionary<Type, EntityTypeInfo> entityTypes,
Dictionary<Type, EdmEnumType> enumTypes, Dictionary<Type, EdmComplexType> complexTypes)
{
foreach (PropertyInfo clrProperty in _metadataProvider.GetProperties(ClrType))
if (!_metadataProvider.IsNotMapped(clrProperty))
{
EdmStructuralProperty? edmProperty = BuildStructuralProperty(entityTypes, enumTypes, complexTypes, clrProperty);
if (edmProperty != null && _metadataProvider.IsDatabaseGenerated(clrProperty))
{
var databaseGenerated = new EdmVocabularyAnnotation(edmProperty, CoreVocabularyModel.ComputedTerm, new EdmBooleanConstant(true));
edmModel.SetVocabularyAnnotation(databaseGenerated);
}
}

if (_isDbQuery)
AddDbQueryKeys();
else
AddKeys();
}
private EdmStructuralProperty? BuildStructuralProperty(Dictionary<Type, EntityTypeInfo> entityTypes,
Dictionary<Type, EdmEnumType> enumTypes, Dictionary<Type, EdmComplexType> complexTypes, PropertyInfo clrProperty)
{
bool isNullable = !_metadataProvider.IsRequired(clrProperty);
Expand Down Expand Up @@ -103,7 +124,7 @@ private void BuildProperty(Dictionary<Type, EntityTypeInfo> entityTypes,
FKeyInfo? fkeyInfo = FKeyInfo.Create(_metadataProvider, entityTypes, this, clrProperty);
if (fkeyInfo != null)
_navigationClrProperties.Add(fkeyInfo);
return;
return null;
}
}
}
Expand All @@ -122,18 +143,8 @@ private void BuildProperty(Dictionary<Type, EntityTypeInfo> entityTypes,
EdmType.AddProperty(edmProperty);
if (_metadataProvider.IsKey(clrProperty))
_keyProperties.Add(new KeyValuePair<PropertyInfo, EdmStructuralProperty>(clrProperty, edmProperty));
}
public void BuildProperties(Dictionary<Type, EntityTypeInfo> entityTypes,
Dictionary<Type, EdmEnumType> enumTypes, Dictionary<Type, EdmComplexType> complexTypes)
{
foreach (PropertyInfo clrProperty in _metadataProvider.GetProperties(ClrType))
if (!_metadataProvider.IsNotMapped(clrProperty))
BuildProperty(entityTypes, enumTypes, complexTypes, clrProperty);

if (_isDbQuery)
AddDbQueryKeys();
else
AddKeys();
return edmProperty;
}
public override String ToString()
{
Expand Down
4 changes: 2 additions & 2 deletions source/OdataToEntity/ModelBuilder/OeEdmModelBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,18 @@ private EdmAction BuildAction(OeOperationConfiguration operationConfiguration, D
public EdmModel BuildEdmModel(params IEdmModel[] refModels)
{
AddOperations();
var edmModel = new EdmModel(false);

Dictionary<Type, EntityTypeInfo> entityTypeInfos = BuildEntityTypes(refModels);
foreach (EntityTypeInfo typeInfo in entityTypeInfos.Values)
if (!typeInfo.IsRefModel)
typeInfo.BuildProperties(entityTypeInfos, _enumTypes, _complexTypes);
typeInfo.BuildStructuralProperties(edmModel, entityTypeInfos, _enumTypes, _complexTypes);

foreach (EntityTypeInfo typeInfo in entityTypeInfos.Values)
if (!typeInfo.IsRefModel)
foreach (FKeyInfo fkeyInfo in typeInfo.NavigationClrProperties)
fkeyInfo.BuildNavigationProperty();

var edmModel = new EdmModel(false);
edmModel.AddElements(_enumTypes.Values);
foreach (KeyValuePair<Type, EdmEnumType> enumType in _enumTypes)
edmModel.SetClrType(enumType.Value, enumType.Key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ public virtual PropertyInfo[] GetProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
}
public virtual bool IsDatabaseGenerated(PropertyInfo propertyInfo)
{
DatabaseGeneratedAttribute attribute = propertyInfo.GetCustomAttribute<DatabaseGeneratedAttribute>();
return attribute != null && attribute.DatabaseGeneratedOption != DatabaseGeneratedOption.None;
}
public virtual bool IsKey(PropertyInfo propertyInfo)
{
return propertyInfo.GetCustomAttribute(typeof(KeyAttribute)) != null;
Expand Down
15 changes: 12 additions & 3 deletions source/OdataToEntity/ModelBuilder/OeJsonSchemaGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OData.Edm.Vocabularies.V1;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;

namespace OdataToEntity.ModelBuilder
Expand Down Expand Up @@ -36,7 +39,7 @@ private void WriteDefinitions(Utf8JsonWriter writer)
WriteDefinitions(writer, edmModel);
writer.WriteEndObject();
}
public static void WriteDefinitions(Utf8JsonWriter writer, IEdmModel edmModel)
public void WriteDefinitions(Utf8JsonWriter writer, IEdmModel edmModel)
{
foreach (IEdmSchemaElement schemaElement in edmModel.SchemaElements)
if (schemaElement is IEdmEntityType entityType)
Expand All @@ -47,7 +50,7 @@ public static void WriteDefinitions(Utf8JsonWriter writer, IEdmModel edmModel)
else if (schemaElement is IEdmEnumType enumType)
WriteEnum(writer, enumType);
}
private static void WriteEntity(Utf8JsonWriter writer, IEdmEntityType entityType)
private void WriteEntity(Utf8JsonWriter writer, IEdmEntityType entityType)
{
writer.WritePropertyName(entityType.Name);
writer.WriteStartObject();
Expand Down Expand Up @@ -150,7 +153,7 @@ private static void WriteProperties(Utf8JsonWriter writer, IEdmModel edmModel)
writer.WriteEndObject();
}
}
private static void WriteStructuralProperty(Utf8JsonWriter writer, IEdmStructuralProperty structuralProperty)
private void WriteStructuralProperty(Utf8JsonWriter writer, IEdmStructuralProperty structuralProperty)
{
if (structuralProperty.Type.Definition is IEdmEnumType enumType)
{
Expand Down Expand Up @@ -221,8 +224,14 @@ private static void WriteStructuralProperty(Utf8JsonWriter writer, IEdmStructura
writer.WritePropertyName(structuralProperty.Name);
writer.WriteStartObject();
writer.WriteString("type", typeName);

if (format != null)
writer.WriteString("format", format);

IEdmVocabularyAnnotation? annotation = _edmModel.FindVocabularyAnnotations<IEdmVocabularyAnnotation>(structuralProperty, CoreVocabularyModel.ComputedTerm).SingleOrDefault();
if (annotation != null && annotation.Value is IEdmBooleanConstantExpression expression && expression.Value)
writer.WriteBoolean("readOnly", true);

writer.WriteEndObject();
}
}
Expand Down
5 changes: 5 additions & 0 deletions test/OdataToEntity.Test.Ef6.SqlServer/EdmModelBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ private static String FixNamesInSchema(String schema)
}
xschemas[1].Remove();

var annotations = xschemas[0].Elements().Where(x => x.Name.LocalName == "Annotations").ToList();
foreach (XElement annotation in annotations)
annotation.Remove();
xschemas[0].Add(annotations);

using (var stream = new MemoryStream())
using (var xwriter = XmlWriter.Create(stream, new XmlWriterSettings() { Indent = true, Encoding = new UTF8Encoding(false) }))
{
Expand Down
3 changes: 2 additions & 1 deletion test/OdataToEntity.Test.Linq2Db/EdmModelBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ private static String FixNamesInSchema(String schema)
foreach (XElement xelement in xschema.Elements())
{
XAttribute xattribute = xelement.Attribute("Name");
xattribute.SetValue(xattribute.Value.Replace(linq2db.Name, efCore.Name));
if (xattribute != null)
xattribute.SetValue(xattribute.Value.Replace(linq2db.Name, efCore.Name));
}

using (var stream = new MemoryStream())
Expand Down

0 comments on commit e507855

Please sign in to comment.