前言

本文我们来探讨下映射动态模型的几种方式,相信一部分童鞋项目有这样的需求,比如每天/每小时等生成一张表,此种动态模型映射非常常见,经我摸索,这里给出每一步详细思路,希望能帮助到没有任何头绪的童鞋,本文以.NET Core 3.1控制台,同时以SQL Server数据库作为示例演示(其他数据库同理照搬),由于会用到内置APi,因版本不同可能比如构造函数需略微进行调整即可。注:虽为示例代码,但我将其作为实际项目皆已进行封装,基本完全通用。本文略长,请耐心。

动态映射模型引入前提

首先我们给出所需要用到的特性以及对应枚举,看注释一看便知

public enum CustomTableFormat
{
/// <summary>
/// 每天,(yyyyMMdd)
/// </summary>
[Description("每天")]
DAY,
/// <summary>
/// 每小时,(yyyyMMddHH)
/// </summary>
[Description("每小时")]
HOUR,
/// <summary>
/// 每分钟(yyyyMMddHHmm)
/// </summary>
[Description("每分钟")]
MINUTE
} [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class EfEntityAttribute : Attribute
{
/// <summary>
/// 是否启用动态生成表
/// </summary>
public bool EnableCustomTable { get; set; } = false;
/// <summary>
/// 动态生成表前缀
/// </summary>
public string Prefix { get; set; }
/// <summary>
/// 表生成规则
/// </summary>
public CustomTableFormat Format { get; set; } = CustomTableFormat.DAY; public override string ToString()
{
if (EnableCustomTable)
{
return string.IsNullOrEmpty(Prefix) ? Format.FormatToDate() : $"{Prefix}{Format.FormatToDate()}";
}
return base.ToString();
}
} public static class CustomTableFormatExetension
{
public static string FormatToDate(this CustomTableFormat tableFormat)
{
return tableFormat switch
{
CustomTableFormat.DAY => DateTime.Now.ToString("yyyyMMdd"),
CustomTableFormat.HOUR => DateTime.Now.ToString("yyyyMMddHH"),
CustomTableFormat.MINUTE => DateTime.Now.ToString("yyyyMMddHHmm"),
_ => DateTime.Now.ToString("yyyyMMdd"),
};
}
}

通过定义特性,主要出发点基于两点考虑:其一:由外部注入模型而非写死DbSet属性访问、其二:每个模型可定义动态映射表规则

动态映射模型方式(一)

首先我们给出需要用到的上下文,为方便演示我们以每分钟自动映射模型为例

public class EfDbContext : DbContext
{
public string Date { get; set; } = CustomTableFormat.MINUTE.FormatToDate();
public EfDbContext(DbContextOptions<EfDbContext> options) : base(options)
{ }
}

动态模型即指表名不同,比如我们实现每天/每小时/每分钟动态映射模型和生成一张表。在下面接口中我们需要用到每分钟生成一张表格式,所以在上下文中定义每分钟属性。第一种方式则是通过实现IModelCacheKeyFactory接口,此接口将指定上下文下所有模型表名进行了缓存,所以我们可以根据所需动态模型表名进行更改即可,如下:

public class CustomModelCacheKeyFactory : IModelCacheKeyFactory
{
public object Create(DbContext context)
{
var efDbContext = context as EfDbContext;
if (efDbContext != null)
{
return (context.GetType(), efDbContext.Date);
}
return context.GetType();
}
}

上述其实现貌似感觉有点看不太懂,主要这是直接实现接口一步到位,底层本质则是额外调用实例一个缓存键类,我们将上述改为如下两步则一目了然

public class CustomModelCacheKeyFactory : ModelCacheKeyFactory
{
private string _date;
public CustomModelCacheKeyFactory(ModelCacheKeyFactoryDependencies dependencies)
: base(dependencies)
{ }
public override object Create(DbContext context)
{
if (context is EfDbContext efDbContext)
{
_date = efDbContext.Date;
} return new CustomModelCacheKey(_date, context);
}
} public class CustomModelCacheKey : ModelCacheKey
{
private readonly Type _contextType;
private readonly string _date;
public CustomModelCacheKey(string date, DbContext context) : base(context)
{
_date = date;
_contextType = context.GetType();
} public virtual bool Equals(CustomModelCacheKey other)
=> _contextType == other._contextType && _date == other._date; public override bool Equals(object obj)
=> (obj is CustomModelCacheKey otherAsKey) && Equals(otherAsKey); public override int GetHashCode() => _date.GetHashCode();
}

然后在OnModelCreating方法里面进行扫描特性标识模型进行注册,如下:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entityMethod = typeof(ModelBuilder).GetMethod(nameof(modelBuilder.Entity),
new Type[] { }); var assembly = Assembly.GetExecutingAssembly(); //【1】使用Entity方法注册
foreach (var type in assembly.ExportedTypes)
{
if (!(type.GetCustomAttribute(typeof(EfEntityAttribute)) is EfEntityAttribute attribute))
{
continue;
} if (type.IsNotPublic || type.IsAbstract || type.IsSealed
|| type.IsGenericType
|| type.ContainsGenericParameters)
{
continue;
} entityMethod.MakeGenericMethod(type)
.Invoke(modelBuilder, new object[] { });
} //【2】使用IEntityTypeConfiguration<T>注册
modelBuilder.ApplyConfigurationsFromAssembly(assembly); base.OnModelCreating(modelBuilder);
}

上述第一种方式则通过反射将模型注册,其本质则是调用modeBuilder.Entity方法,若我们在模型上使用注解,则对应也会将其应用

但注解不够灵活,比如要标识联合主键,则只能使用Fluent APi,所以我们通过在外部实现IEntityTypeConfiguration进行注册,然后EF Core提供针对该接口程序集注册,其底层本质也是扫描程序集,两种方式都支持,不用再担心外部模型注册问题

紧接着我们给出测试模型,表名为当前分钟,表名利用注解则不行(值必须为常量),所以我们使用如下第二种映射模型

[EfEntity(EnableCustomTable = true, Format = CustomTableFormat.MINUTE)]
public class Test
{
[Table(DateTime.Now.ToString("yyyyMMdd"))]
public int Id { get; set; }
public string Name { get; set; }
} public class TestEntityTypeConfiguration : IEntityTypeConfiguration<Test>
{
public void Configure(EntityTypeBuilder<Test> builder)
{
builder.ToTable(DateTime.Now.ToString("yyyyMMddHHmm"));
}
}

上述第二种配置未尝不可,但我们还有更加简洁一步到位的操作,所以这里删除上述第二种方式,因为在OnModelCreating方法里面,我们反射了调用了Entity方法,所以我们直接将反射调用Entity方法强制转换为EntityTypeBuilder,在已有基础上,代码做了重点标识

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var entityMethod = typeof(ModelBuilder).GetMethod(nameof(modelBuilder.Entity), new Type[] { });
var assembly = Assembly.GetExecutingAssembly(); //【1】使用Entity方法注册
foreach (var type in assembly.ExportedTypes)
{
if (!(type.GetCustomAttribute(typeof(EfEntityAttribute)) is EfEntityAttribute attribute))
{
continue;
} if (type.IsNotPublic || type.IsAbstract || type.IsSealed
|| type.IsGenericType
|| type.ContainsGenericParameters)
{
continue;
} // 强制转换为EntityTypeBuilder
var entityBuilder = (EntityTypeBuilder)entityMethod.MakeGenericMethod(type)
.Invoke(modelBuilder, new object[] { }); if (attribute.EnableCustomTable)
{
entityBuilder.ToTable(attribute.ToString());
}
} //【2】使用IEntityTypeConfiguration<T>注册
modelBuilder.ApplyConfigurationsFromAssembly(assembly); base.OnModelCreating(modelBuilder);
}

最后则是注入上下文,这里我们将内外部容器进行区分(EF Core为何分内部容器,具体原因请参看文章《EntityFramework Core 3.x上下文构造函数可以注入实例呢?》)

因在实际项目中上下文可能需要在上下文构造函数中注入其他接口,比如我们就有可能在上下文构造函数中注入接口从而根据具体接口实现来更改表架构或不同表名规则等等

static IServiceProvider Initialize()
{
var services = new ServiceCollection(); services.AddEntityFrameworkSqlServer()
.AddDbContext<EfDbContext>(
(serviceProvider, options) =>
options.UseSqlServer("server=.;database=efcore;uid=sa;pwd=sa123;")
.UseInternalServiceProvider(serviceProvider)); services.Replace(ServiceDescriptor.Singleton<IModelCacheKeyFactory, CustomModelCacheKeyFactory>()); return services.BuildServiceProvider();
}

由于我们已区分EF Core内外部容器,所以在替换自定义缓存键工厂时,不能再像如下直接调用ReplaceService方法替换,势必会抛出异常

options.UseSqlServer("server=.;database=efcore;uid=sa;pwd=sa123;")
.ReplaceService<IModelCacheKeyFactory, CustomModelCacheKeyFactory>()

同时谨记在非Web项目中利用EF Core始终要使用作用域(scope)来释放上下文,不像Web可基于HTTP请求作为scope,最后我们测试如下

using (var scope1 = ServiceProvider.CreateScope())
{
var context1 = scope1.ServiceProvider.GetService<EfDbContext>(); context1.Database.EnsureCreated(); var type = context1.Model.FindEntityType(typeof(Test)); Console.WriteLine(type?.GetTableName()); var tests = context1.Set<Test>().ToList();
} Thread.Sleep(60000); using (var scope2 = ServiceProvider.CreateScope())
{
var context2 = scope2.ServiceProvider.GetService<EfDbContext>(); context2.Database.EnsureCreated(); var type = context2.Model.FindEntityType(typeof(Test)); Console.WriteLine(type?.GetTableName()); var tests1 = context2.Set<Test>().ToList();
}

为方便看到实际效果,我们构建两个scope,然后睡眠一分钟,在界面上打印输出表名,若两分钟后打印表名不一致,说明达到预期

动态映射模型方式(二)

上述我们使用每分钟规则动态映射表,同时可针对不同模型有各自规则(前缀,每小时或每天)等等,这是第一种方式

如果对第一种方式实现完全看懂了,可能会有所疑惑,因为第一种方式其接口生命周期为单例,若不需要岂不还是会将上下文中所有模型都会进行缓存吗

调用OnModelCreating方法只是进行模型构建,但我们现直接调用内置APi来手动使用所有模型,此时将不再缓存,所以不再需要IModelCacheKeyFactory接口

对EF Core稍微了解一点的话,我们知道OnModelCreating方法仅仅只会调用一次,我们通过手动使用和处置所有模型,换言之每次请求都会使用新的模型,说了这么多,那么我们到底该如何做呢?

如果看过我之前原理分析的话,大概能知道EntityFramework Core对于模型的处理(除却默认模型缓存)分为三步,除却模型缓存:构建模型,使用模型,处置模型。

我们将OnModelCreating方法代码全部直接复制过来,只是多了上面三步而已,在我们实例化ModelBuilder时,我们需要提供对应数据库默认约定,然后使用模型、处置模型,结果变成如下这般

 services.AddEntityFrameworkSqlServer()
.AddDbContext<EfDbContext>(
(serviceProvider, options) => { options.UseSqlServer("server=.;database=efcore;uid=sa;pwd=sa123;")
.UseInternalServiceProvider(serviceProvider); var conventionSet = SqlServerConventionSetBuilder.Build(); var modelBuilder = new ModelBuilder(conventionSet); // OnModelCreating方法,代码复制 options.UseModel(modelBuilder.Model); modelBuilder.FinalizeModel();
)};

运行第一种方式测试代码,然后么有问题

问题来了,要是有多个数据库,岂不是都要像上述再来一遍?上述实现本质上是每次构造一个上下文则会构建并重新使用新的模型,所以我们将其统一放到上下文构造函数中去,然后写个扩展方法构建模型,如下:

public static class ModelBuilderExetension
{
public static ModelBuilder BuildModel(this ModelBuilder modelBuilder)
{ var entityMethod = typeof(ModelBuilder).GetMethod(nameof(modelBuilder.Entity), new Type[] { });
var assembly = Assembly.GetExecutingAssembly(); //【1】使用Entity方法注册
foreach (var type in assembly.ExportedTypes)
{
if (!(type.GetCustomAttribute(typeof(EfEntityAttribute)) is EfEntityAttribute attribute))
{
continue;
} if (type.IsNotPublic || type.IsAbstract || type.IsSealed
|| type.IsGenericType
|| type.ContainsGenericParameters)
{
continue;
} var entityBuilder = (EntityTypeBuilder)entityMethod.MakeGenericMethod(type)
.Invoke(modelBuilder, new object[] { }); if (attribute.EnableCustomTable)
{
entityBuilder.ToTable(attribute.ToString());
}
} //【2】使用IEntityTypeConfiguration<T>注册
modelBuilder.ApplyConfigurationsFromAssembly(assembly); return modelBuilder;
}
}

最后在上下文构造函数中,简洁调用,如下:

public class EfDbContext : DbContext
{
public string Date { get; set; } = CustomTableFormat.MINUTE.FormatToDate();
public EfDbContext(DbContextOptions<EfDbContext> options) : base(options)
{
//提供不同数据库默认约定
ConventionSet conventionSet = null; if (Database.ProviderName == "Microsoft.EntityFrameworkCore.SqlServer")
{
conventionSet = SqlServerConventionSetBuilder.Build();
}
else if (Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqllite")
{
conventionSet = SqliteConventionSetBuilder.Build();
}
else if (Database.ProviderName == "Microsoft.EntityFrameworkCore.MySql")
{
conventionSet = MySqlConventionSetBuilder.Build();
} var modelBuilder = new ModelBuilder(conventionSet); var optionBuilder = new DbContextOptionsBuilder(options); //使用模型
optionBuilder.UseModel(modelBuilder.Model); //处置模型
modelBuilder.FinalizeModel();
} protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//构建模型
modelBuilder.BuildModel(); base.OnModelCreating(modelBuilder);
}
}

动态映射模型表生成

看到这里,细心的你不知道有没有发现,我写的打印结果怎么成功了,居然没抛出任何异常,实际情况是必须会抛出异常,因为我们只做到了模型动态映射,但表自动生成我在此之前将其忽略了,如下:

表如何生成这个也看实际情况分析,比如SQL Server写个作业每天自动生成表等,若需兼容多个数据库,怕是有点麻烦

我没花太多时间去看源码,稍微看了下,碰碰运气或许能直接找到根据模型来创建表的接口实现,结果好像没有,即使有也比较麻烦,那么我们就手动构建SQL语句或者通过lambda构建也可

上下文中实现其特性需动态生成的模型我们可以获取得到,然后搞个定时器每分钟去执行生成对应表,针对不同数据库类型,我们可以通过如下属性获取得到(和包同名)

// 比如SQL Server:Microsoft.EntityFrameworkCore.SqlServer
context.Database.ProviderName

这里我以SQL Server数据库为例,其他数据库比如MySqL、Sqlite唯一区别则是自增长设置和列类型不同而已,创建表,通过五部分组成:表是否存在,表名,主键,所有列,约束。我们定义如下:

internal sealed class CustomTableModel
{
public CustomEntityType CustomEntityType { get; set; } public string TableName { get; set; } = string.Empty;
public string CheckTable { get; set; } = string.Empty;
public string PrimaryKey { get; set; } = string.Empty;
public string Columns { get; set; } = string.Empty;
public string Constraint { get; set; } = string.Empty; public override string ToString()
{
var placeHolder = $"{CheckTable} create table {TableName} ({PrimaryKey} {Columns}"; placeHolder = string.IsNullOrEmpty(Constraint) ? $"{placeHolder.TrimEnd(',')})" : $"{placeHolder}{Constraint})"; return placeHolder.Replace("@placeholder_table_name", CustomEntityType.ToString());
}
}

由于每次生成只有表名不同,所以我们将整个表数据结构进行缓存,在其内部将表名进行替换就好。整个实现逻辑如下:

public static void Execute()
{
using var scope = Program.ServiceProvider.CreateScope();
var context = scope.ServiceProvider.GetService<EfDbContext>(); context.Database.EnsureCreated(); var cache = scope.ServiceProvider.GetService<IMemoryCache>(); var cacheKey = context.GetType().FullName; if (!cache.TryGetValue(cacheKey, out List<CustomTableModel> models))
{
lock (_syncObject)
{
if (!cache.TryGetValue(cacheKey, out models))
{
models = CreateModels(context); models = cache.Set(cacheKey, models, new MemoryCacheEntryOptions { Size = 100, Priority = CacheItemPriority.High });
}
}
} Create(context, models);
} private static void Create(EfDbContext context, List<CustomTableModel> models)
{
foreach (var m in models)
{
context.Execute(m.ToString());
}
} internal static void CreateEntityTypes(CustomEntityType customEntityType)
{
EntityTypes.Add(customEntityType);
}

上述标红部分很重要,为什么呢?让其先执行OnModelCreating方法,也就是说我们必须保证所有模型已经构建完毕,我们才能在上下文中拿到所有模型元数据

接下来则是在OnModeCreating方法中,在启动自动映射模型的基础上,添加如下代码(当然也需检查表名是否存在重复):

 if (attribute.EnableCustomTable)
{
entityBuilder.ToTable(attribute.ToString()); var customType = new CustomEntityType()
{
ClrType = type,
Prefix = attribute.Prefix,
Format = attribute.Format
}; var existTable = CreateCustomTable.EntityTypes.FirstOrDefault(c => c.ToString() == customType.ToString()); if (existTable != null)
{
throw new ArgumentNullException($"Cannot use table '{customType}' for entity type '{type.Name}' since it is being used for entity type '{existTable.ClrType.Name}' ");
} CreateCustomTable.CreateEntityTypes(customType);
}

相信构建SQL语句这块都不在话下,就不再给出了,真的有需要的童鞋,可私信我,人比较多的话,我会将兼容不同数据库的SQL语句构建都会放到github上去,控制台入口方法调用如下:

private const int TIME_INTERVAL_IN_MILLISECONDS = 60000;
private static Timer _timer { get; set; }
public static IServiceProvider ServiceProvider { get; set; }
static void Main(string[] args)
{
ServiceProvider = Initialize(); //初始化时检查一次
CreateCustomTable.Execute(); //定时检查
_timer = new Timer(TimerCallback, null, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite); using (var scope1 = ServiceProvider.CreateScope())
{
var context1 = scope1.ServiceProvider.GetService<EfDbContext>(); context1.Database.EnsureCreated(); var type = context1.Model.FindEntityType(typeof(Test1)); Console.WriteLine(type?.GetTableName()); var tests = context1.Set<Test1>().ToList();
} Thread.Sleep(60000); using (var scope2 = ServiceProvider.CreateScope())
{
var context2 = scope2.ServiceProvider.GetService<EfDbContext>(); context2.Database.EnsureCreated(); var type = context2.Model.FindEntityType(typeof(Test2)); Console.WriteLine(type?.GetTableName()); var tests1 = context2.Set<Test2>().ToList();
} Console.ReadKey(); }

接下来则是通过定义上述定时器,回调调用上述Execute方法,如下:

static void TimerCallback(object state)
{
var watch = new Stopwatch(); watch.Start(); CreateCustomTable.Execute(); _timer.Change(Math.Max(0, TIME_INTERVAL_IN_MILLISECONDS - watch.ElapsedMilliseconds), Timeout.Infinite);
}

最后我们来两个模型测试下实际效果

[EfEntity(EnableCustomTable = true, Prefix = "test1", Format = CustomTableFormat.MINUTE)]
public class Test1
{
public int Id { get; set; }
public int UserId { get; set; }
public string Name { get; set; }
} public class Test1EntityTypeConfiguration : IEntityTypeConfiguration<Test1>
{
public void Configure(EntityTypeBuilder<Test1> builder)
{
builder.HasKey(k => new { k.Id, k.UserId });
}
} [EfEntity(EnableCustomTable = true, Prefix = "test2", Format = CustomTableFormat.MINUTE)]
public class Test2
{
public int Id { get; set; }
public int UserId { get; set; }
public string Name { get; set; }
} public class Test2EntityTypeConfiguration : IEntityTypeConfiguration<Test2>
{
public void Configure(EntityTypeBuilder<Test2> builder)
{
builder.HasKey(k => new { k.Id, k.UserId });
}
}

总结

最后的最后,老规矩,实现动态映射模型有如上两种方式,通过手动构建SQL语句并缓存,总结如下!

使用IModelCacheKeyFactory

手动使用模型、处置模型

兼容不同数据库,手动构建SQL语句并缓存

EntityFramework Core如何映射动态模型?的更多相关文章

  1. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  2. EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public?

    前言 不知我们是否思考过一个问题,在关系映射中对于导航属性的访问修饰符是否一定必须为public呢?如果从未想过这个问题,那么我们接下来来探讨这个问题. EF 6.x和EF Core 何种情况下必须配 ...

  3. EntityFramework Core 学习笔记 —— 创建模型

    原文地址:https://docs.efproject.net/en/latest/modeling/index.html 前言: EntityFramework 使用一系列的约定来从我们的实体类细节 ...

  4. EntityFramework Core一劳永逸动态加载模型,我们要知道些什么呢?

    前言 这篇文章源于一位问我的童鞋:在EntityFramework Core中如何动态加载模型呢?在学习EntityFramwork时关于这个问题已有对应园友给出答案,故没有过多研究,虽然最后解决了这 ...

  5. EntityFramework Core饥饿加载忽略导航属性问题

    前言 .NET Core项目利用EntityFramework Core作为数据访问层一直在进行中,一直没有过多的去关注背后生成的SQL语句,然后老大捞出日志文件一看,恩,有问题了,所以本文产生了,也 ...

  6. EntityFramework Core 自动绑定模型映射

    笔者最近在和同事共同开发项目时,需要从他们提供的包含数据库实体类型的类库中读取实体信息绑定到自己的项目中(但是都在同一个解决方案里),所以很直接的一种方式就是把项目中所有的实体都以 public Db ...

  7. ASP.NET Core 2.2 十九. Action参数的映射与模型绑定

    前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.int等类型,也包含Json等复杂类型,本文详细分享一下这一过程.(ASP.NET ...

  8. Cookies 初识 Dotnetspider EF 6.x、EF Core实现dynamic动态查询和EF Core注入多个上下文实例池你知道有什么问题? EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)

    Cookies   1.创建HttpCookies Cookie=new HttpCookies("CookieName");2.添加内容Cookie.Values.Add(&qu ...

  9. EntityFramework Core是否可以映射私有属性呢?了解一下。

    前言 最近几天身体有点抱恙,说话都需要勇气,痛哭.今天简短的写一点探索性的内容,仅供了解,感谢您的阅读. EF Core映射私有属性 在EF 6.x系列中写过一篇文章可以映射私有属性,说明EF的灵活性 ...

随机推荐

  1. js下 Day03、DOM操作--节点方法

    语法:parentNode.appendChild(child) 功能:向父节点的子节点列表的末尾添加新的子节点 语法:parentNode.removeChild(child) 功能:从子节点列表中 ...

  2. [日常摸鱼]Uva11178Morley's Theorem-几何

    题意:给一个$\Delta ABC$,分别做三个角的三等分线相交成$\Delta DEF$,求出$D,E,F$的坐标. 直接根据题意模拟 #include<cstdio> #include ...

  3. Yii2 给表添加字段后报错 Getting unknown property

    手动在数据库中添加了image字段 然后再模型类Image中的 rule方法也将image的验证规则放进去了 但是在 $model = new Image 后,使用$model->iamge 还 ...

  4. Logistic 回归-原理及应用

    公号:码农充电站pro 主页:https://codeshellme.github.io 上一篇文章介绍了线性回归模型,它用于处理回归问题. 这次来介绍一下 Logistic 回归,中文音译为逻辑回归 ...

  5. iOS 自定义tabBarController(中间弧形)

    效果图 1.在继承自UITabBarController的自定义controller中调用以下方法(LZCustomTabbar为自定义的tabbar) - (void)viewDidAppear:( ...

  6. swift笔记简录

    一,变量和常量 /***************************基本数据类型*************************/ /****************************** ...

  7. 操作系统微内核和Dubbo微内核,有何不同?

    你好,我是 yes. 在之前的文章已经提到了 RPC 的核心,想必一个 RPC 通信大致的流程和基本原理已经清晰了. 这篇文章借着 Dubbo 来说说微内核这种设计思想,不会扯到 Dubbo 某个具体 ...

  8. ES6中class的使用+继承

    一.Class 介绍+基本语法(1).介绍通过class关键字,可以定义类.基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的 ...

  9. java内部类 之private 属性对其他对象的访问限制

    public class InnerClass1 { private class Content { private int i; public int value() { // TODO Auto- ...

  10. Hive日期函数总结(转学习使用)

    一.时间戳函数 1.获取当前时区的UNIX时间戳:select unix_timestamp(); 2.将指定时间转为UNIX时间戳: select unix_timestamp('2012-03-0 ...