diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index 299c91e5..8fd2938a 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -120,6 +120,13 @@ 清空状态数据 + + + 根据 lambda 条件删除数据 + + + + 添加 @@ -388,5 +395,14 @@ + + + 批量注入 Repository,可以参考代码自行调整 + + + + + + diff --git a/FreeSql.Tests/FreeSql.Tests/DataAnnotations/EFCoreAttributeTest.cs b/FreeSql.Tests/FreeSql.Tests/DataAnnotations/EFCoreAttributeTest.cs new file mode 100644 index 00000000..f3dd26ae --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/DataAnnotations/EFCoreAttributeTest.cs @@ -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(); + fsql.CodeFirst.SyncStructure(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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; } + } + } +} diff --git a/FreeSql/FreeSqlBuilder.cs b/FreeSql/FreeSqlBuilder.cs index 51a13af8..4a07cecf 100644 --- a/FreeSql/FreeSqlBuilder.cs +++ b/FreeSql/FreeSqlBuilder.cs @@ -286,7 +286,7 @@ namespace FreeSql break; } } - //处理 MaxLength + //处理 MaxLength、EFCore 特性 ret.Aop.ConfigEntityProperty += new EventHandler((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((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}"; + } }); }