我想将相同结构的表按照不同的类别建立多张表,用Ef如何实现?

目前项目遇到一个问题,我想将相同结构的表按照不同的类别建立多张表,用Ef如何实现?

例如:一个气象设备,可以采集“温度”“湿度”等多个要素,在数据库内对应了一个设备表,一个 要素表(这个主要记录要素的一些描述),一个要素历史数据 表(记录数据),设备与要素一对多的关系,要素与要素历史表一对多的关系。这种情况的话所有要素的历史数据都会被存储在一个表中。我现在的想法是为每一个 要素都建立一个历史表(历史表的机构是一样的,时间,值,备注 三个字段)。 
我这么考虑是因为数据量问题,要素采集一分钟一条数,一天就是1440条,那如果有两个设备一个设备有10个要素一年就是1千多万条数据。而且如果分开放历史数据的话查询某个要素的历史信息时可以只查看某张表就好。

        public  DbSet<Station> Stations { get; set; }
        public  DbSet<Device> Devices { get; set; }
        public  DbSet<Tag> Tags { get; set; }

        /// <summary>
        /// 创建历史数据表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tag"></param>
        public void CreateTagHisTable(Tag tag)
        {
            try
            {
                var sqlSqlServer = $" IF OBJECT_ID('{tag.TableName}', 'U') IS NULL   CREATE TABLE {tag.TableName}   ( [TimeStamp] bigint PRIMARY KEY,[Value] float,[Quality] int );";
                 
                Database.ExecuteSqlCommand(sqlSqlServer);
                //RunInfoPanel.Instance.Write(sqlSqlServer);

            }
            catch (Exception e)
            {
                RunInfoPanel.Instance.Write($"创建表【{tag.TableName}】失败!!!原因:{e}");
            }
        }

以上是dbcontext部分代码,Station,Device,Tag,分别是对站点设备要素的描述信息,tag有好多个,然后我现在暂时是使用sql语句创建的表,表名是tag内的“TableName” 属性,结构也特别简单,就是一个时间,数值和数据质量。

这个问题使用sql语句可以正常解决,但现在我使用的时EF框架,就想问下能否通过Ef实现这个问题。 

除了  dbcontext.database.sqlquery<>方法,这种sql语句之外,
我没想到其他方案。

要素很多吗?不多就建实体吧,多的话就像楼上一样写SQL,不过这样就不能搞关系了

要素比较多,根据地面观测字典内要素数量非常巨大,而且还有就是每次项目的要素类型是不固定的,我无法将所有要素都建立一个实体

实体类就共用一个

然后用 dbcontext.Database.SqlQuery<实体>(strSql)来实现吧 

或者将其他属性放在基类表  继承实现 如果有什么统一需要更改的 就改一下基类

可能你没理解我的意思,我现在的需求是表结构是一样的,但是表名不同,对应到实体上就是一个实体根据Name属性建立表名进行区分,你说的建立子类是在表数量已知且较少的前提下,如果我有20个要素不可能去建立20个子类吧?

你这个我去年就做过了,在gis地图上mouseup引发事件,弹出子表div.我就是用的EF.是环保的水文监测。

不知是不是我没有理解到,还是您思路上有些问题,您这儿跑到SQL里面去创建一个空表,是干嘛呢?有这个必要吗。直接再写个 类,HistroyByTag。public dbset<historyByTag> Historyes。下面您需要什么时候用,直接用 linq语句获取相应的historys就可以了。sql语句到数据库里面去重新读取,还创建临时表,不太可取。
另外项目最终是硬件终端通过物联传到数据库的文本,您在编写时候要考虑解析的类。

可能我上面说的不太清楚,其实我要问的就是你说的使用HistroyByTag类如何在数据库中建立多张表,我知 道 dbset<historyByTag> Histroryes 这个方法,这个只会在数据库中建立一张历史表,通过tag.Id与 tag表相联系,但是我现在不想将所有要素的历史数据放到一张表内,因为如果有20个要素,一个要素1天1440条数据那一年就是一千多万条,这到后期数 据量太大,也不利于单独查询。我想通过Tag的数量,更改tag的内部属性(TableName)动态建立历史表,这些历史表将每个tag的历史分开存 放。也就是说有10个tag就有10张历史表,有20个tag就有20个历史表。我不知道如何使用ef实现,所以我只能使用sql语句根据传入的 TableName动态创建表。

所有历史数据就是应该放一张表里面,你放1张表跟放N张表没什么不同。在ef里面这个几千万的linq查询,区别不大。按您的思路,创建几百万个历史表反而效率更高?你还不如创建json文本流放数据库里面。xml流也可以。

仔细想了下,其实您这初始想法很对的,确实是我没明白您的意思。现在明白了,其实您是想看EF里面能否动态创建子类并相应保存的机制。这个我还没使用过, 但我想是肯定行的。我有空帮您看下文档,顺便自己也学习下。但您那用SQL去创建肯定不妥,我那json保存也是笨办法。

我觉得还是应该所有历史数据都应该放1张表里面,应为实体的属性都一样啊。那以前数据库设计的基础er图设计时候,属性完全一样就是该一张表啊。为什么要分开呢。应该还是我最初想法正确些,新建历史类实体,linq语句得到相应数据。

理论上应该要分开的。
查询效率会高很多。
而且日志分析也清晰明了。
假设有10个日志表,每个100w记录。
那我从100W里查,肯定比1个表1000W里查要快。
而且定位问题也要准。

其实,拆分存储,就是数据库分库分表的实际业务需求。
我们有一个项目,需要把图片二进制保存入数据库。
大家别问我为什么不用url,老板强制要求,我也没办法。
这就导致一条数据的某个img字段,可能有80M
这样的数据来10条。就会明显感觉到很慢了。
因此我们就需要分库分表。

其实我感觉,还是使用 dbcontext.database.sqlquery<> 解决最合适。
这是一个泛型方法,你只需要在<>中输入你要的Model类型就好了。
sql查询出来,会自动映射到Model

对的,确实不应该放N张表。比如分页。有N页的数据,难道去建N张数据表反而效率更高?所以不应该纠结这个。简单的事情弄复杂了。

是的,目前我使用的方法就是这个,使用sql语句动态创建表,然后通过database.sqlquery<history>(sql语句) 的形式进行查询。其余的表是通过dbset<>的形式让ef自动创建。现在就是不知道ef是否支持我的想法。

没问题的,
只要你查询出的history字段名字一样就可以了。
哪怕不一样,你也可以通过 sql 字段 as history属性 来解决

那你们也不用拆分数据库和数据表啊,这等同于分页单独建数据表,更不用说,还要重建数据库了。这能比直接用linq语句论坛顶帖机筛选数据更快?比如我们处理分页,如果出现分页后某些页的数据访问会卡,难道我们会去找数据库的原因,而不是修改和测试分页的方法代码?

怎么说呢,数据量大了,分库分表是很正常的。
只是楼主类似于这里先拆分好了。
这并没什么不可取的。
其实现在分布式蛮多的,阿里的用户表存储可能达到16个,每个用户登录,会根据用户的编号取模,确定去不同的库抓取用户信息。
这显然也是同一个逻辑。因为一个表存储所有数据,只适合中小型的数据量,并且一行数据的kb不多的情况。

针对这个问题我决定不去纠结如何Ef啦,我决定使用sql语句去进行操作,至于32楼说的dapper听过没有用过,我会去了解下。多谢各位热情的讨论,分不多就平分吧

但是当实体相同时Ef会只为其建立一张表,并不会建立多张表吧?我们现在讨论的是将这个历史表如何分为多个,就像一个设备有多个要素,一个要素有多个历史记录;使用ef建立的话数据库内只会有1张设备表,1张要素表,1张历史记录表。

这种情况,通常可以先针对每个设备建立一个数据表,作为原始数据记录;同一要素对应不同设备的,可以建立一个要素数据表,把不同设备数据作为不同的列,作 为数据对比参考表。另外,你对数据库的基本概念理解好像有点问题:设备和要素都是表头(列),数据是对着表头一行行填充上去的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值