Skip to content

Commit

Permalink
Merge pull request #177 from linq2db/master
Browse files Browse the repository at this point in the history
Release 5.6.0
  • Loading branch information
sdanyliv authored Sep 15, 2021
2 parents f9f0d3a + 109e613 commit 4565918
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 29 deletions.
2 changes: 1 addition & 1 deletion Build/linq2db.Default.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>5.5.0</Version>
<Version>5.6.0</Version>

<Authors>Svyatoslav Danyliv, Igor Tkachev, Dmitry Lukashenko, Ilya Chudin</Authors>
<Product>Linq to DB</Product>
Expand Down
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<PackageVersion Include="NUnit" Version="3.13.2" />
<PackageVersion Include="FluentAssertions" Version="5.10.3" />

<PackageVersion Include="linq2db" Version="3.4.3" />
<PackageVersion Include="linq2db.Tools" Version="3.4.3" />
<PackageVersion Include="linq2db" Version="3.4.4" />
<PackageVersion Include="linq2db.Tools" Version="3.4.4" />

<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="1.0.0" />

Expand Down
2 changes: 1 addition & 1 deletion NuGet/linq2db.EntityFrameworkCore.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<dependencies>
<group targetFramework=".NETStandard2.1">
<dependency id="Microsoft.EntityFrameworkCore.Relational" version="5.0.2" />
<dependency id="linq2db" version="3.4.3" />
<dependency id="linq2db" version="3.4.4" />
</group>
</dependencies>
</metadata>
Expand Down
38 changes: 29 additions & 9 deletions Source/LinqToDB.EntityFrameworkCore/EFCoreMetadataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ public T[] GetAttributes<T>(Type type, bool inherit = true) where T : Attribute
if (tableAttribute != null)
return new[] { (T)(Attribute)new TableAttribute(tableAttribute.Name) { Schema = tableAttribute.Schema } };
}
else if (_model != null && typeof(T) == typeof(InheritanceMappingAttribute))
{
if (et != null)
{
var derivedEntities = _model.GetEntityTypes().Where(e => e.BaseType == et && e.GetDiscriminatorValue() != null).ToList();

return
derivedEntities.Select(e =>
(T)(Attribute)new InheritanceMappingAttribute
{
Type = e.ClrType,
Code = e.GetDiscriminatorValue()
}
)
.ToArray();
}

}

return Array.Empty<T>();
}
Expand Down Expand Up @@ -190,11 +208,13 @@ public T[] GetAttributes<T>(Type type, MemberInfo memberInfo, bool inherit = tru

if (prop != null)
{
var discriminator = et.GetDiscriminatorProperty();

var isPrimaryKey = prop.IsPrimaryKey();
var primaryKeyOrder = 0;
if (isPrimaryKey)
{
var pk = prop.FindContainingPrimaryKey();
var pk = prop.FindContainingPrimaryKey()!;
primaryKeyOrder = pk.Properties.Select((p, i) => new { p, index = i })
.FirstOrDefault(v => CompareProperty(v.p, memberInfo))?.index ?? 0;
}
Expand All @@ -204,16 +224,15 @@ public T[] GetAttributes<T>(Type type, MemberInfo memberInfo, bool inherit = tru
var annotations = prop.GetAnnotations();
if (_annotationProvider != null && storeObjectId != null)
{
var column = prop.FindColumn(storeObjectId.Value) as IColumn;
if (column != null)
if (prop.FindColumn(storeObjectId.Value) is IColumn column)
annotations = annotations.Concat(_annotationProvider.For(column));
}

var isIdentity = annotations
.Any(a =>
{
if (a.Name.EndsWith(":ValueGenerationStrategy"))
return a.Value?.ToString().Contains("Identity") == true;
return a.Value?.ToString()!.Contains("Identity") == true;
if (a.Name.EndsWith(":Autoincrement"))
return a.Value is bool b && b;
Expand Down Expand Up @@ -256,6 +275,7 @@ public T[] GetAttributes<T>(Type type, MemberInfo memberInfo, bool inherit = tru
IsPrimaryKey = isPrimaryKey,
PrimaryKeyOrder = primaryKeyOrder,
IsIdentity = isIdentity,
IsDiscriminator = discriminator == prop
}
};
}
Expand Down Expand Up @@ -413,7 +433,7 @@ protected bool Equals(SqlTransparentExpression other)
return ReferenceEquals(this, other);
}

public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
Expand Down Expand Up @@ -459,7 +479,7 @@ public override int GetHashCode()
Expression.Constant(DefaultValue.GetValue(p.ParameterType), p.ParameterType),
_mappingSource?.FindMapping(p.ParameterType))).ToArray();
var newExpression = _dependencies.MethodCallTranslatorProvider.Translate(_model, objExpr, methodInfo, parametersArray, _logger);
var newExpression = _dependencies.MethodCallTranslatorProvider.Translate(_model, objExpr, methodInfo, parametersArray, _logger!);
if (newExpression != null)
{
if (!methodInfo.IsStatic)
Expand Down Expand Up @@ -492,7 +512,7 @@ public override int GetHashCode()
{
var objExpr = new SqlTransparentExpression(Expression.Constant(DefaultValue.GetValue(type), type), _mappingSource?.FindMapping(propInfo));
var newExpression = _dependencies.MemberTranslatorProvider.Translate(objExpr, propInfo, propInfo.GetMemberType(), _logger);
var newExpression = _dependencies.MemberTranslatorProvider.Translate(objExpr, propInfo, propInfo.GetMemberType(), _logger!);
if (newExpression != null)
{
var parametersArray = new Expression[] { objExpr };
Expand Down Expand Up @@ -572,7 +592,7 @@ string PrepareExpressionText(Expression? expr)
var left = newExpression.GetType().GetProperty("Left")?.GetValue(newExpression) as Expression;
var right = newExpression.GetType().GetProperty("Right")?.GetValue(newExpression) as Expression;

var operand = newExpression.GetType().GetProperty("OperatorType")?.GetValue(newExpression).ToString();
var operand = newExpression.GetType().GetProperty("OperatorType")?.GetValue(newExpression)!.ToString();

var operandExpr = operand switch
{
Expand Down Expand Up @@ -643,7 +663,7 @@ private static Expression UnwrapConverted(Expression expr)
if (expr is SqlFunctionExpression func)
{
if (string.Equals(func.Name, "COALESCE", StringComparison.InvariantCultureIgnoreCase) &&
func.Arguments.Count == 2 && func.Arguments[1].NodeType == ExpressionType.Extension)
func.Arguments!.Count == 2 && func.Arguments[1].NodeType == ExpressionType.Extension)
return UnwrapConverted(func.Arguments[0]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ public override ISqlExpression GetExpression(
{
var mc = (MethodCallExpression) expression;
if (!mc.Method.IsStatic)
knownExpressions.Add(mc.Object);
knownExpressions.Add(mc.Object!);
knownExpressions.AddRange(mc.Arguments);
}
else
{
var me = (MemberExpression) expression;
knownExpressions.Add(me.Expression);
knownExpressions.Add(me.Expression!);
}

var pams = new List<ISqlExpression?>(knownExpressions.Select(_ => (ISqlExpression?) null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
/// </summary>
/// <param name="expression">Query expression.</param>
/// <returns>Query result.</returns>
public object Execute(Expression expression)
public object? Execute(Expression expression)
{
return QueryProvider.Execute(expression);
}
Expand Down Expand Up @@ -107,7 +107,7 @@ TResult IAsyncQueryProvider.ExecuteAsync<TResult>(Expression expression, Cancell
{
var item = typeof(TResult).GetGenericArguments()[0];
var method = _executeAsyncMethodInfo.MakeGenericMethod(item);
return (TResult) method.Invoke(QueryProvider, new object[] { expression, cancellationToken });
return (TResult) method.Invoke(QueryProvider, new object[] { expression, cancellationToken })!;
}

/// <summary>
Expand Down Expand Up @@ -158,14 +158,15 @@ IEnumerator IEnumerable.GetEnumerator()
/// <returns>Query result as <see cref="IAsyncEnumerable{T}"/>.</returns>
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
{
return QueryProvider.ExecuteAsyncEnumerable<T>(Expression, cancellationToken).Result.GetAsyncEnumerator(cancellationToken);
return Task.Run(() => QueryProvider.ExecuteAsyncEnumerable<T>(Expression, cancellationToken),
cancellationToken).Result.GetAsyncEnumerator(cancellationToken);
}

/// <summary>
/// Returns generated SQL for specific LINQ query.
/// </summary>
/// <returns>Generated SQL.</returns>
public override string ToString()
public override string? ToString()
{
return QueryProvider.ToString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public static Task<Dictionary<TKey, TSource>> ToDictionaryAsyncEF<TSource, TKey>
this IQueryable<TSource> source,
Func<TSource, TKey> keySelector,
CancellationToken cancellationToken = default)
where TKey: notnull
=> EntityFrameworkQueryableExtensions.ToDictionaryAsync(source, keySelector, cancellationToken);

/// <inheritdoc cref="EntityFrameworkQueryableExtensions.ToDictionaryAsync{TSource, TKey, TElement}(IQueryable{TSource}, Func{TSource, TKey}, Func{TSource, TElement}, CancellationToken)"/>
Expand All @@ -47,6 +48,7 @@ public static Task<Dictionary<TKey,TElement>> ToDictionaryAsyncEF<TSource,TKey,T
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
CancellationToken cancellationToken = default)
where TKey : notnull
=> EntityFrameworkQueryableExtensions.ToDictionaryAsync(source, keySelector, elementSelector, cancellationToken);

/// <inheritdoc cref="EntityFrameworkQueryableExtensions.ToDictionaryAsync{TSource, TKey, TElement}(IQueryable{TSource}, Func{TSource, TKey}, Func{TSource, TElement}, IEqualityComparer{TKey}, CancellationToken)"/>
Expand All @@ -56,6 +58,7 @@ public static Task<Dictionary<TKey,TElement>> ToDictionaryAsyncEF<TSource,TKey,T
Func<TSource,TElement> elementSelector,
IEqualityComparer<TKey> comparer,
CancellationToken cancellationToken = default)
where TKey : notnull
=> EntityFrameworkQueryableExtensions.ToDictionaryAsync(source, keySelector, elementSelector, comparer, cancellationToken);

/// <inheritdoc cref="EntityFrameworkQueryableExtensions.FirstAsync{TSource}(IQueryable{TSource}, CancellationToken)"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public virtual void TestIdentityMapping()
using var connection = context.CreateLinqToDbConnection();

var ed = connection.MappingSchema.GetEntityDescriptor(typeof(WithIdentity));
var pk = ed.Columns.Where(c => c.IsPrimaryKey).Single();
var pk = ed.Columns.Single(c => c.IsPrimaryKey);

pk.IsIdentity.Should().BeTrue();
}
Expand All @@ -32,7 +32,7 @@ public virtual void TestNoIdentityMapping()
using var connection = context.CreateLinqToDbConnection();

var ed = connection.MappingSchema.GetEntityDescriptor(typeof(NoIdentity));
var pk = ed.Columns.Where(c => c.IsPrimaryKey).Single();
var pk = ed.Columns.Single(c => c.IsPrimaryKey);

pk.IsIdentity.Should().BeFalse();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Microsoft.EntityFrameworkCore;

namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests.Models.Inheritance
{
public abstract class BlogBase
{
public int Id { get; set; }
public string BlogType { get; set; } = null!;
}

public class Blog : BlogBase
{
public string Url { get; set; } = null!;
}

public class RssBlog : BlogBase
{
public string Url { get; set; } = null!;
}

public abstract class ShadowBlogBase
{
public int Id { get; set; }
public string BlogType { get; set; } = null!;
}

public class ShadowBlog : ShadowBlogBase
{
public string Url { get; set; } = null!;
}

public class ShadowRssBlog : ShadowBlogBase
{
public string Url { get; set; } = null!;
}

public class InheritanceContext : DbContext
{
public InheritanceContext(DbContextOptions options) : base(options)
{

}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BlogBase>()
.HasDiscriminator(b => b.BlogType)
.HasValue<Blog>("blog_base")
.HasValue<RssBlog>("blog_rss");

modelBuilder.Entity<BlogBase>()
.Property(e => e.BlogType)
.HasColumnName("BlogType")
.HasMaxLength(200);

modelBuilder.Entity<Blog>()
.Property(b => b.Url)
.HasColumnName("Url");

modelBuilder.Entity<RssBlog>()
.Property(b => b.Url)
.HasColumnName("Url");

modelBuilder.Entity<Blog>().ToTable("Blogs");
modelBuilder.Entity<RssBlog>().ToTable("Blogs");

/////

modelBuilder.Entity<ShadowBlogBase>()
.HasDiscriminator()
.HasValue<ShadowBlog>("blog_base")
.HasValue<ShadowRssBlog>("blog_rss");

modelBuilder.Entity<ShadowBlogBase>()
.Property(e => e.BlogType)
.HasColumnName("BlogType")
.HasMaxLength(200);

modelBuilder.Entity<ShadowBlog>()
.Property(b => b.Url)
.HasColumnName("Url");

modelBuilder.Entity<ShadowRssBlog>()
.Property(b => b.Url)
.HasColumnName("Url");

modelBuilder.Entity<ShadowBlog>().ToTable("ShadowBlogs");
modelBuilder.Entity<ShadowRssBlog>().ToTable("ShadowBlogs");
}

public DbSet<BlogBase> Blogs { get; set; } = null!;
public DbSet<ShadowBlogBase> ShadowBlogs { get; set; } = null!;
}

}
Loading

0 comments on commit 4565918

Please sign in to comment.