EF的表连接方法Include() - nlh774

本文详细对比了Entity Framework (EF) 中的两种表连接方式:Join() 和 Include()。介绍了它们的不同应用场景、语法特点及如何实现两张表的连接。Join() 更具灵活性,适用于复杂的连接需求;而 Include() 则简化了外键关联查询的过程。

在EF中表连接常用的有Join()和Include(),两者都可以实现两张表的连接,但又有所不同。

例如有个唱片表Album(AlbumId,Name,CreateDate,GenreId),表中含外键GenreId连接流派表Genre(GenreId,Name)。每个唱片归属唯一一个流派,一个流派可以对应多个唱片。

1.Join(),两表不必含有外键关系,需要代码手动指定连接外键相等(具有可拓展性,除了值相等,还能指定是>,<以及其他对两表的相应键的关系),以及结果字段。

重载方式(是扩展方法,第一个参数带this,代表自身):

1.public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector);

2.public static IQueryable<TResult> Join<TOuter, TInner, TKey, TResult>(this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector, IEqualityComparer<TKey> comparer);

那么可以这么写两个表的连接:

var wholeRecord = dc.Album.Join(dc.Genre, a => a.GenreId, g => g.GenreId, (a, g) => new { a.AlbumId,a.Name,g.GenreId,g.Name;

这样就选取除了两表的AlbumId,Name,GenreId,Name。

2.Include(),两表必须含有外键关系,只需要指定键名对应的类属性名即可,不需指定结果字段(即全部映射)。默认搜索某表时,不会顺带查询外键表,直到真正使用时才会再读取数据库查询;若是使用 Include(),则会在读取本表时把指定的外键表信息也读出来。

重载方式:

//位于namespace System.Data.Entity.Infrastructure
public DbQuery<TResult> Include(string path);
//位于namespace System.Data.Entity,务必引入才能找到该方法。否则只看到上个方法
public static IQueryable<T> Include<T, TProperty>(this IQueryable<T> source, Expression<Func<T, TProperty>> path) where T : class;
        public static IQueryable<T> Include<T>(this IQueryable<T> source, string path) where T : class;

可以这么写:

//EF已经生成了Album和Genre的数据库映射模型类以及导航属性
var wholeRecord=dc.Album.Include("Genre");
//或者
//var wholeRecord=dc.Album.Include(a=>Genre);

这样数据库就执行了一个左连接,把Album和Genre的所有字段全部连起来了,并且Include()是立即查询的,像ToList()一样,不会稍后延迟优化后再加载。

这样其实效率很低,因为如果两张表记录很大,那么连接是个费时费资源的事情,建议少用,或者先筛选出需要的结果集再连接。

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <linux/if.h> #include <linux/if_arp.h> #include <linux/wireless.h> #include <netinet/in.h> #include <arpa/inet.h> #define BUFFER_SIZE 4096 #define NETLINK_WIFI_EVENT 29 // 自定义 netlink 协议号 // 自定义 Wi-Fi 事件结构 typedef struct wifi_event { uint32_t ifindex; // 接口索引 uint8_t mac[6]; // MAC 地址 uint16_t event_type; // 事件类型: 0=连接, 1=断开 } wifi_event_t; int create_netlink_socket() { struct sockaddr_nl addr; int sock; int on = 1; // 创建 netlink socket if ((sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { perror("socket"); return -1; } memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; // 设置 SO_RCVBUF 选项避免 ENOBUFS 错误 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &on, sizeof(on)) { perror("setsockopt SO_RCVBUF"); close(sock); return -1; } // 绑定 socket if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) { perror("bind"); close(sock); return -1; } return sock; } void parse_netlink_message(int sock) { char buf[BUFFER_SIZE]; struct iovec iov = { buf, sizeof(buf) }; struct sockaddr_nl sa; struct msghdr msg = { .msg_name = &sa, .msg_namelen = sizeof(sa), .msg_iov = &iov, .msg_iovlen = 1 }; struct nlmsghdr *nlh; int len; while (1) { len = recvmsg(sock, &msg, 0); if (len < 0) { perror("recvmsg"); continue; } // 处理所有 netlink 消息 for (nlh = (struct nlmsghdr *)buf; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) { // 检查消息是否结束 if (nlh->nlmsg_type == NLMSG_DONE) break; // 处理错误消息 if (nlh->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = NLMSG_DATA(nlh); fprintf(stderr, "Netlink error: %s\n", strerror(-err->error)); continue; } // 处理接口变化事件 if (nlh->nlmsg_type == RTM_NEWLINK || nlh->nlmsg_type == RTM_DELLINK) { struct ifinfomsg *ifi = NLMSG_DATA(nlh); char ifname[IF_NAMESIZE]; if (if_indextoname(ifi->ifi_index, ifname) == NULL) { perror("if_indextoname"); continue; } // 检查是否是无线接口 struct iwreq wrq; memset(&wrq, 0, sizeof(wrq)); strncpy(wrq.ifr_name, ifname, IFNAMSIZ); if (ioctl(sock, SIOCGIWNAME, &wrq) == 0) { // 无线接口事件 printf("Wi-Fi interface event: %s (%s)\n", ifname, (nlh->nlmsg_type == RTM_NEWLINK) ? "UP" : "DOWN"); } } } } } int main() { int sock = create_netlink_socket(); if (sock < 0) { fprintf(stderr, “Failed to create netlink socket\n”); return 1; } printf("Listening for Wi-Fi events...\n"); parse_netlink_message(sock); close(sock); return 0; } 没收到WIFI设备连接的消息帮忙修改一下
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值