mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 17:20:49 +08:00 
			
		
		
		
	- 增加 FreeSqlBuilder 自动识别 EFCore 实体特性 Key/Required/NotMapped/Table/Column;#4
This commit is contained in:
		@@ -120,6 +120,13 @@
 | 
			
		||||
            清空状态数据
 | 
			
		||||
            </summary>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:FreeSql.DbSet`1.RemoveAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
 | 
			
		||||
            <summary>
 | 
			
		||||
            根据 lambda 条件删除数据
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="predicate"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:FreeSql.DbSet`1.Add(`0)">
 | 
			
		||||
            <summary>
 | 
			
		||||
            添加
 | 
			
		||||
@@ -388,5 +395,14 @@
 | 
			
		||||
            <param name="that"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
        <member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
 | 
			
		||||
            <summary>
 | 
			
		||||
            批量注入 Repository,可以参考代码自行调整
 | 
			
		||||
            </summary>
 | 
			
		||||
            <param name="services"></param>
 | 
			
		||||
            <param name="globalDataFilter"></param>
 | 
			
		||||
            <param name="assemblies"></param>
 | 
			
		||||
            <returns></returns>
 | 
			
		||||
        </member>
 | 
			
		||||
    </members>
 | 
			
		||||
</doc>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,110 @@
 | 
			
		||||
using FreeSql.Tests.DataContext.SqlServer;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Data.SqlClient;
 | 
			
		||||
using Xunit;
 | 
			
		||||
 | 
			
		||||
namespace FreeSql.Tests.DataAnnotations
 | 
			
		||||
{
 | 
			
		||||
    public class EFCoreAttributeTest
 | 
			
		||||
    {
 | 
			
		||||
        IFreeSql fsql => g.sqlserver;
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void TableAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb01>();
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb02>();
 | 
			
		||||
            Assert.Equal("eftesttb_01", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb01)).DbName);
 | 
			
		||||
            Assert.Equal("dbo.eftesttb_02", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb02)).DbName);
 | 
			
		||||
        }
 | 
			
		||||
        [System.ComponentModel.DataAnnotations.Schema.Table("eftesttb_01")]
 | 
			
		||||
        class eftesttb01
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
        [System.ComponentModel.DataAnnotations.Schema.Table("eftesttb_02", Schema = "dbo")]
 | 
			
		||||
        class eftesttb02
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void MaxLengthAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb03>();
 | 
			
		||||
            Assert.Equal("NVARCHAR(100)", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb03)).ColumnsByCs["title"].Attribute.DbType);
 | 
			
		||||
        }
 | 
			
		||||
        class eftesttb03
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.MaxLength(100)]
 | 
			
		||||
            public string title { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void RequiredAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb04>();
 | 
			
		||||
            Assert.False(fsql.CodeFirst.GetTableByEntity(typeof(eftesttb04)).ColumnsByCs["title"].Attribute.IsNullable);
 | 
			
		||||
        }
 | 
			
		||||
        class eftesttb04
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.Required]
 | 
			
		||||
            public string title { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void NotMappedAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb05>();
 | 
			
		||||
            Assert.False(fsql.CodeFirst.GetTableByEntity(typeof(eftesttb05)).ColumnsByCsIgnore.ContainsKey("id"));
 | 
			
		||||
            Assert.True(fsql.CodeFirst.GetTableByEntity(typeof(eftesttb05)).ColumnsByCsIgnore.ContainsKey("title"));
 | 
			
		||||
        }
 | 
			
		||||
        class eftesttb05
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.Schema.NotMapped]
 | 
			
		||||
            public string title { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void ColumnAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb06>();
 | 
			
		||||
            Assert.Equal("title_01", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title1"].Attribute.Name);
 | 
			
		||||
            Assert.Equal("title_02", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title2"].Attribute.Name);
 | 
			
		||||
            Assert.Equal("title_03", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title3"].Attribute.Name);
 | 
			
		||||
 | 
			
		||||
            Assert.Equal(99, fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title2"].Attribute.Position);
 | 
			
		||||
            Assert.Equal(98, fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title3"].Attribute.Position);
 | 
			
		||||
 | 
			
		||||
            Assert.Equal("NVARCHAR(255)", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title1"].Attribute.DbType);
 | 
			
		||||
            Assert.Equal("NVARCHAR(255)", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title2"].Attribute.DbType);
 | 
			
		||||
            Assert.Equal("VARCHAR(100)", fsql.CodeFirst.GetTableByEntity(typeof(eftesttb06)).ColumnsByCs["title3"].Attribute.DbType);
 | 
			
		||||
        }
 | 
			
		||||
        class eftesttb06
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.Schema.Column("title_01")]
 | 
			
		||||
            public string title1 { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.Schema.Column("title_02", Order = 99)]
 | 
			
		||||
            public string title2 { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.Schema.Column("title_03", Order = 98, TypeName = "varchar(100)")]
 | 
			
		||||
            public string title3 { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [Fact]
 | 
			
		||||
        public void KeyAttribute()
 | 
			
		||||
        {
 | 
			
		||||
            fsql.CodeFirst.SyncStructure<eftesttb07>();
 | 
			
		||||
            Assert.True(fsql.CodeFirst.GetTableByEntity(typeof(eftesttb07)).ColumnsByCs["title"].Attribute.IsPrimary);
 | 
			
		||||
        }
 | 
			
		||||
        class eftesttb07
 | 
			
		||||
        {
 | 
			
		||||
            public Guid id { get; set; }
 | 
			
		||||
            [System.ComponentModel.DataAnnotations.Key]
 | 
			
		||||
            public string title { get; set; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -286,7 +286,7 @@ namespace FreeSql
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                //处理 MaxLength
 | 
			
		||||
                //处理 MaxLength、EFCore 特性
 | 
			
		||||
                ret.Aop.ConfigEntityProperty += new EventHandler<Aop.ConfigEntityPropertyEventArgs>((s, e) =>
 | 
			
		||||
                {
 | 
			
		||||
                    object[] attrs = null;
 | 
			
		||||
@@ -296,17 +296,83 @@ namespace FreeSql
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
 | 
			
		||||
                    var maxlenAttr = attrs?.Where(a => {
 | 
			
		||||
                    var dyattr = attrs?.Where(a => {
 | 
			
		||||
                        return ((a as Attribute)?.TypeId as Type)?.Name == "MaxLengthAttribute";
 | 
			
		||||
                    }).FirstOrDefault();
 | 
			
		||||
                    if (maxlenAttr != null)
 | 
			
		||||
                    if (dyattr != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        var lenProp = maxlenAttr.GetType().GetProperties().Where(a => a.PropertyType.IsNumberType()).FirstOrDefault();
 | 
			
		||||
                        if (lenProp != null && int.TryParse(string.Concat(lenProp.GetValue(maxlenAttr, null)), out var tryval) && tryval != 0)
 | 
			
		||||
                        var lenProp = dyattr.GetType().GetProperties().Where(a => a.PropertyType.IsNumberType()).FirstOrDefault();
 | 
			
		||||
                        if (lenProp != null && int.TryParse(string.Concat(lenProp.GetValue(dyattr, null)), out var tryval) && tryval != 0)
 | 
			
		||||
                        {
 | 
			
		||||
                            e.ModifyResult.StringLength = tryval;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    dyattr = attrs?.Where(a => {
 | 
			
		||||
                        return ((a as Attribute)?.TypeId as Type)?.FullName == "System.ComponentModel.DataAnnotations.RequiredAttribute";
 | 
			
		||||
                    }).FirstOrDefault();
 | 
			
		||||
                    if (dyattr != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        e.ModifyResult.IsNullable = false;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    dyattr = attrs?.Where(a => {
 | 
			
		||||
                        return ((a as Attribute)?.TypeId as Type)?.FullName == "System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute";
 | 
			
		||||
                    }).FirstOrDefault();
 | 
			
		||||
                    if (dyattr != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        e.ModifyResult.IsIgnore = true;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    dyattr = attrs?.Where(a => {
 | 
			
		||||
                        return ((a as Attribute)?.TypeId as Type)?.FullName == "System.ComponentModel.DataAnnotations.Schema.ColumnAttribute";
 | 
			
		||||
                    }).FirstOrDefault();
 | 
			
		||||
                    if (dyattr != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        var name = dyattr.GetType().GetProperties().Where(a => a.PropertyType == typeof(string) && a.Name == "Name").FirstOrDefault()?.GetValue(dyattr, null)?.ToString();
 | 
			
		||||
                        short.TryParse(string.Concat(dyattr.GetType().GetProperties().Where(a => a.PropertyType == typeof(int) && a.Name == "Order").FirstOrDefault()?.GetValue(dyattr, null)), out var order);
 | 
			
		||||
                        var typeName = dyattr.GetType().GetProperties().Where(a => a.PropertyType == typeof(string) && a.Name == "TypeName").FirstOrDefault()?.GetValue(dyattr, null)?.ToString();
 | 
			
		||||
 | 
			
		||||
                        if (string.IsNullOrEmpty(name) == false)
 | 
			
		||||
                            e.ModifyResult.Name = name;
 | 
			
		||||
                        if (order != 0)
 | 
			
		||||
                            e.ModifyResult.Position = order;
 | 
			
		||||
                        if (string.IsNullOrEmpty(typeName) == false)
 | 
			
		||||
                            e.ModifyResult.DbType = typeName;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    dyattr = attrs?.Where(a => {
 | 
			
		||||
                        return ((a as Attribute)?.TypeId as Type)?.FullName == "System.ComponentModel.DataAnnotations.KeyAttribute";
 | 
			
		||||
                    }).FirstOrDefault();
 | 
			
		||||
                    if (dyattr != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        e.ModifyResult.IsPrimary = true;
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                //EFCore 特性
 | 
			
		||||
                ret.Aop.ConfigEntity += new EventHandler<Aop.ConfigEntityEventArgs>((s, e) =>
 | 
			
		||||
                {
 | 
			
		||||
                    object[] attrs = null;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        attrs = e.EntityType.GetCustomAttributes(false).ToArray(); //.net core 反射存在版本冲突问题,导致该方法异常
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
 | 
			
		||||
                    var dyattr = attrs?.Where(a => {
 | 
			
		||||
                        return ((a as Attribute)?.TypeId as Type)?.FullName == "System.ComponentModel.DataAnnotations.Schema.TableAttribute";
 | 
			
		||||
                    }).FirstOrDefault();
 | 
			
		||||
                    if (dyattr != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        var name = dyattr.GetType().GetProperties().Where(a => a.PropertyType == typeof(string) && a.Name == "Name").FirstOrDefault()?.GetValue(dyattr, null)?.ToString();
 | 
			
		||||
                        var schema = dyattr.GetType().GetProperties().Where(a => a.PropertyType == typeof(string) && a.Name == "Schema").FirstOrDefault()?.GetValue(dyattr, null)?.ToString();
 | 
			
		||||
                        if (string.IsNullOrEmpty(name) == false && string.IsNullOrEmpty(schema) == false)
 | 
			
		||||
                            e.ModifyResult.Name = $"{schema}.{name}";
 | 
			
		||||
                        else if (string.IsNullOrEmpty(name) == false)
 | 
			
		||||
                            e.ModifyResult.Name = name;
 | 
			
		||||
                        else if (string.IsNullOrEmpty(schema) == false)
 | 
			
		||||
                            e.ModifyResult.Name = $"{schema}.{e.EntityType.Name}";
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user