.NET生成MongoDB中的主键ObjectId
前言
因为很多场景下我们需要在创建MongoDB数据的时候提前生成好主键为了返回或者通过主键查询创建的业务,像EF中我们可以生成Guid来,本来想着要不要实现一套MongoDB中ObjectId的,结果发现网上各种各样的实现都有,不过好在阅读C#MongoDB驱动mongo-csharp-driver代码的时候发现有ObjectId.GenerateNewId()的方法提供,我们可以直接调用即可,不需要我们在花费多余的时间设计重写了。
MongoDB ObjectId类型概述
每次插入一条数据系统都会自动插入一个_id键,键值不可以重复,它可以是任何类型的,也可以手动的插入,默认情况下它的数据类型是ObjectId,由于MongoDB在设计之初就是用作分布式数据库,所以使用ObjectId可以避免不同数据库中_id的重复(如果使用自增的方式在分布式系统中就会出现重复的_id的值)。
ObjectId使用12字节的存储空间,每个字节可以存储两个十六进制数字,所以一共可以存储24个十六进制数字组成的字符串,在这24个字符串中,前8位表示时间戳,接下来6位是一个机器码,接下来4位表示进程id,最后6位表示计数器。
601e2b6b a3203c c89f 2d31aa
↑ ↑ ↑ ↑
时间戳 机器码 进程ID 随机数
MongoDB.Driver驱动安装
1、直接命令自动安装
Install-Package MongoDB.Driver
2、搜索Nuget手动安装
调用生成主键ObjectId
var primarykeyId = ObjectId.GenerateNewId();
//输出:641c54b2e674000035001dc2
mongo-csharp-driver ObjectId详解
关于ObjectId的生成原理大家阅读如下源码即可。
/* Copyright 2010-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Security;
using System.Threading; namespace MongoDB.Bson
{
/// <summary>
/// Represents an ObjectId (see also BsonObjectId).
/// </summary>
#if NET45
[Serializable]
#endif
public struct ObjectId : IComparable<ObjectId>, IEquatable<ObjectId>, IConvertible
{
// private static fields
private static readonly ObjectId __emptyInstance = default(ObjectId);
private static readonly int __staticMachine = (GetMachineHash() + GetAppDomainId()) & 0x00ffffff;
private static readonly short __staticPid = GetPid();
private static int __staticIncrement = (new Random()).Next(); // private fields
private readonly int _a;
private readonly int _b;
private readonly int _c; // constructors
/// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="bytes">The bytes.</param>
public ObjectId(byte[] bytes)
{
if (bytes == null)
{
throw new ArgumentNullException("bytes");
}
if (bytes.Length != 12)
{
throw new ArgumentException("Byte array must be 12 bytes long", "bytes");
} FromByteArray(bytes, 0, out _a, out _b, out _c);
} /// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="bytes">The bytes.</param>
/// <param name="index">The index into the byte array where the ObjectId starts.</param>
internal ObjectId(byte[] bytes, int index)
{
FromByteArray(bytes, index, out _a, out _b, out _c);
} /// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="timestamp">The timestamp (expressed as a DateTime).</param>
/// <param name="machine">The machine hash.</param>
/// <param name="pid">The PID.</param>
/// <param name="increment">The increment.</param>
public ObjectId(DateTime timestamp, int machine, short pid, int increment)
: this(GetTimestampFromDateTime(timestamp), machine, pid, increment)
{
} /// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="timestamp">The timestamp.</param>
/// <param name="machine">The machine hash.</param>
/// <param name="pid">The PID.</param>
/// <param name="increment">The increment.</param>
public ObjectId(int timestamp, int machine, short pid, int increment)
{
if ((machine & 0xff000000) != 0)
{
throw new ArgumentOutOfRangeException("machine", "The machine value must be between 0 and 16777215 (it must fit in 3 bytes).");
}
if ((increment & 0xff000000) != 0)
{
throw new ArgumentOutOfRangeException("increment", "The increment value must be between 0 and 16777215 (it must fit in 3 bytes).");
} _a = timestamp;
_b = (machine << 8) | (((int)pid >> 8) & 0xff);
_c = ((int)pid << 24) | increment;
} /// <summary>
/// Initializes a new instance of the ObjectId class.
/// </summary>
/// <param name="value">The value.</param>
public ObjectId(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
} var bytes = BsonUtils.ParseHexString(value);
FromByteArray(bytes, 0, out _a, out _b, out _c);
} // public static properties
/// <summary>
/// Gets an instance of ObjectId where the value is empty.
/// </summary>
public static ObjectId Empty
{
get { return __emptyInstance; }
} // public properties
/// <summary>
/// Gets the timestamp.
/// </summary>
public int Timestamp
{
get { return _a; }
} /// <summary>
/// Gets the machine.
/// </summary>
public int Machine
{
get { return (_b >> 8) & 0xffffff; }
} /// <summary>
/// Gets the PID.
/// </summary>
public short Pid
{
get { return (short)(((_b << 8) & 0xff00) | ((_c >> 24) & 0x00ff)); }
} /// <summary>
/// Gets the increment.
/// </summary>
public int Increment
{
get { return _c & 0xffffff; }
} /// <summary>
/// Gets the creation time (derived from the timestamp).
/// </summary>
public DateTime CreationTime
{
get { return BsonConstants.UnixEpoch.AddSeconds(Timestamp); }
} // public operators
/// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is less than the second ObjectId.</returns>
public static bool operator <(ObjectId lhs, ObjectId rhs)
{
return lhs.CompareTo(rhs) < 0;
} /// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is less than or equal to the second ObjectId.</returns>
public static bool operator <=(ObjectId lhs, ObjectId rhs)
{
return lhs.CompareTo(rhs) <= 0;
} /// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId.</param>
/// <returns>True if the two ObjectIds are equal.</returns>
public static bool operator ==(ObjectId lhs, ObjectId rhs)
{
return lhs.Equals(rhs);
} /// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId.</param>
/// <returns>True if the two ObjectIds are not equal.</returns>
public static bool operator !=(ObjectId lhs, ObjectId rhs)
{
return !(lhs == rhs);
} /// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is greather than or equal to the second ObjectId.</returns>
public static bool operator >=(ObjectId lhs, ObjectId rhs)
{
return lhs.CompareTo(rhs) >= 0;
} /// <summary>
/// Compares two ObjectIds.
/// </summary>
/// <param name="lhs">The first ObjectId.</param>
/// <param name="rhs">The other ObjectId</param>
/// <returns>True if the first ObjectId is greather than the second ObjectId.</returns>
public static bool operator >(ObjectId lhs, ObjectId rhs)
{
return lhs.CompareTo(rhs) > 0;
} // public static methods
/// <summary>
/// Generates a new ObjectId with a unique value.
/// </summary>
/// <returns>An ObjectId.</returns>
public static ObjectId GenerateNewId()
{
return GenerateNewId(GetTimestampFromDateTime(DateTime.UtcNow));
} /// <summary>
/// Generates a new ObjectId with a unique value (with the timestamp component based on a given DateTime).
/// </summary>
/// <param name="timestamp">The timestamp component (expressed as a DateTime).</param>
/// <returns>An ObjectId.</returns>
public static ObjectId GenerateNewId(DateTime timestamp)
{
return GenerateNewId(GetTimestampFromDateTime(timestamp));
} /// <summary>
/// Generates a new ObjectId with a unique value (with the given timestamp).
/// </summary>
/// <param name="timestamp">The timestamp component.</param>
/// <returns>An ObjectId.</returns>
public static ObjectId GenerateNewId(int timestamp)
{
int increment = Interlocked.Increment(ref __staticIncrement) & 0x00ffffff; // only use low order 3 bytes
return new ObjectId(timestamp, __staticMachine, __staticPid, increment);
} /// <summary>
/// Packs the components of an ObjectId into a byte array.
/// </summary>
/// <param name="timestamp">The timestamp.</param>
/// <param name="machine">The machine hash.</param>
/// <param name="pid">The PID.</param>
/// <param name="increment">The increment.</param>
/// <returns>A byte array.</returns>
public static byte[] Pack(int timestamp, int machine, short pid, int increment)
{
if ((machine & 0xff000000) != 0)
{
throw new ArgumentOutOfRangeException("machine", "The machine value must be between 0 and 16777215 (it must fit in 3 bytes).");
}
if ((increment & 0xff000000) != 0)
{
throw new ArgumentOutOfRangeException("increment", "The increment value must be between 0 and 16777215 (it must fit in 3 bytes).");
} byte[] bytes = new byte[12];
bytes[0] = (byte)(timestamp >> 24);
bytes[1] = (byte)(timestamp >> 16);
bytes[2] = (byte)(timestamp >> 8);
bytes[3] = (byte)(timestamp);
bytes[4] = (byte)(machine >> 16);
bytes[5] = (byte)(machine >> 8);
bytes[6] = (byte)(machine);
bytes[7] = (byte)(pid >> 8);
bytes[8] = (byte)(pid);
bytes[9] = (byte)(increment >> 16);
bytes[10] = (byte)(increment >> 8);
bytes[11] = (byte)(increment);
return bytes;
} /// <summary>
/// Parses a string and creates a new ObjectId.
/// </summary>
/// <param name="s">The string value.</param>
/// <returns>A ObjectId.</returns>
public static ObjectId Parse(string s)
{
if (s == null)
{
throw new ArgumentNullException("s");
} ObjectId objectId;
if (TryParse(s, out objectId))
{
return objectId;
}
else
{
var message = string.Format("'{0}' is not a valid 24 digit hex string.", s);
throw new FormatException(message);
}
} /// <summary>
/// Tries to parse a string and create a new ObjectId.
/// </summary>
/// <param name="s">The string value.</param>
/// <param name="objectId">The new ObjectId.</param>
/// <returns>True if the string was parsed successfully.</returns>
public static bool TryParse(string s, out ObjectId objectId)
{
// don't throw ArgumentNullException if s is null
if (s != null && s.Length == 24)
{
byte[] bytes;
if (BsonUtils.TryParseHexString(s, out bytes))
{
objectId = new ObjectId(bytes);
return true;
}
} objectId = default(ObjectId);
return false;
} /// <summary>
/// Unpacks a byte array into the components of an ObjectId.
/// </summary>
/// <param name="bytes">A byte array.</param>
/// <param name="timestamp">The timestamp.</param>
/// <param name="machine">The machine hash.</param>
/// <param name="pid">The PID.</param>
/// <param name="increment">The increment.</param>
public static void Unpack(byte[] bytes, out int timestamp, out int machine, out short pid, out int increment)
{
if (bytes == null)
{
throw new ArgumentNullException("bytes");
}
if (bytes.Length != 12)
{
throw new ArgumentOutOfRangeException("bytes", "Byte array must be 12 bytes long.");
} timestamp = (bytes[0] << 24) + (bytes[1] << 16) + (bytes[2] << 8) + bytes[3];
machine = (bytes[4] << 16) + (bytes[5] << 8) + bytes[6];
pid = (short)((bytes[7] << 8) + bytes[8]);
increment = (bytes[9] << 16) + (bytes[10] << 8) + bytes[11];
} // private static methods
private static int GetAppDomainId()
{
#if NETSTANDARD1_5 || NETSTANDARD1_6
return 1;
#else
return AppDomain.CurrentDomain.Id;
#endif
} /// <summary>
/// Gets the current process id. This method exists because of how CAS operates on the call stack, checking
/// for permissions before executing the method. Hence, if we inlined this call, the calling method would not execute
/// before throwing an exception requiring the try/catch at an even higher level that we don't necessarily control.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private static int GetCurrentProcessId()
{
return Process.GetCurrentProcess().Id;
} private static int GetMachineHash()
{
// use instead of Dns.HostName so it will work offline
var machineName = GetMachineName();
return 0x00ffffff & machineName.GetHashCode(); // use first 3 bytes of hash
} private static string GetMachineName()
{
return Environment.MachineName;
} private static short GetPid()
{
try
{
return (short)GetCurrentProcessId(); // use low order two bytes only
}
catch (SecurityException)
{
return 0;
}
} private static int GetTimestampFromDateTime(DateTime timestamp)
{
var secondsSinceEpoch = (long)Math.Floor((BsonUtils.ToUniversalTime(timestamp) - BsonConstants.UnixEpoch).TotalSeconds);
if (secondsSinceEpoch < int.MinValue || secondsSinceEpoch > int.MaxValue)
{
throw new ArgumentOutOfRangeException("timestamp");
}
return (int)secondsSinceEpoch;
} private static void FromByteArray(byte[] bytes, int offset, out int a, out int b, out int c)
{
a = (bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3];
b = (bytes[offset + 4] << 24) | (bytes[offset + 5] << 16) | (bytes[offset + 6] << 8) | bytes[offset + 7];
c = (bytes[offset + 8] << 24) | (bytes[offset + 9] << 16) | (bytes[offset + 10] << 8) | bytes[offset + 11];
} // public methods
/// <summary>
/// Compares this ObjectId to another ObjectId.
/// </summary>
/// <param name="other">The other ObjectId.</param>
/// <returns>A 32-bit signed integer that indicates whether this ObjectId is less than, equal to, or greather than the other.</returns>
public int CompareTo(ObjectId other)
{
int result = ((uint)_a).CompareTo((uint)other._a);
if (result != 0) { return result; }
result = ((uint)_b).CompareTo((uint)other._b);
if (result != 0) { return result; }
return ((uint)_c).CompareTo((uint)other._c);
} /// <summary>
/// Compares this ObjectId to another ObjectId.
/// </summary>
/// <param name="rhs">The other ObjectId.</param>
/// <returns>True if the two ObjectIds are equal.</returns>
public bool Equals(ObjectId rhs)
{
return
_a == rhs._a &&
_b == rhs._b &&
_c == rhs._c;
} /// <summary>
/// Compares this ObjectId to another object.
/// </summary>
/// <param name="obj">The other object.</param>
/// <returns>True if the other object is an ObjectId and equal to this one.</returns>
public override bool Equals(object obj)
{
if (obj is ObjectId)
{
return Equals((ObjectId)obj);
}
else
{
return false;
}
} /// <summary>
/// Gets the hash code.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
int hash = 17;
hash = 37 * hash + _a.GetHashCode();
hash = 37 * hash + _b.GetHashCode();
hash = 37 * hash + _c.GetHashCode();
return hash;
} /// <summary>
/// Converts the ObjectId to a byte array.
/// </summary>
/// <returns>A byte array.</returns>
public byte[] ToByteArray()
{
var bytes = new byte[12];
ToByteArray(bytes, 0);
return bytes;
} /// <summary>
/// Converts the ObjectId to a byte array.
/// </summary>
/// <param name="destination">The destination.</param>
/// <param name="offset">The offset.</param>
public void ToByteArray(byte[] destination, int offset)
{
if (destination == null)
{
throw new ArgumentNullException("destination");
}
if (offset + 12 > destination.Length)
{
throw new ArgumentException("Not enough room in destination buffer.", "offset");
} destination[offset + 0] = (byte)(_a >> 24);
destination[offset + 1] = (byte)(_a >> 16);
destination[offset + 2] = (byte)(_a >> 8);
destination[offset + 3] = (byte)(_a);
destination[offset + 4] = (byte)(_b >> 24);
destination[offset + 5] = (byte)(_b >> 16);
destination[offset + 6] = (byte)(_b >> 8);
destination[offset + 7] = (byte)(_b);
destination[offset + 8] = (byte)(_c >> 24);
destination[offset + 9] = (byte)(_c >> 16);
destination[offset + 10] = (byte)(_c >> 8);
destination[offset + 11] = (byte)(_c);
} /// <summary>
/// Returns a string representation of the value.
/// </summary>
/// <returns>A string representation of the value.</returns>
public override string ToString()
{
var c = new char[24];
c[0] = BsonUtils.ToHexChar((_a >> 28) & 0x0f);
c[1] = BsonUtils.ToHexChar((_a >> 24) & 0x0f);
c[2] = BsonUtils.ToHexChar((_a >> 20) & 0x0f);
c[3] = BsonUtils.ToHexChar((_a >> 16) & 0x0f);
c[4] = BsonUtils.ToHexChar((_a >> 12) & 0x0f);
c[5] = BsonUtils.ToHexChar((_a >> 8) & 0x0f);
c[6] = BsonUtils.ToHexChar((_a >> 4) & 0x0f);
c[7] = BsonUtils.ToHexChar(_a & 0x0f);
c[8] = BsonUtils.ToHexChar((_b >> 28) & 0x0f);
c[9] = BsonUtils.ToHexChar((_b >> 24) & 0x0f);
c[10] = BsonUtils.ToHexChar((_b >> 20) & 0x0f);
c[11] = BsonUtils.ToHexChar((_b >> 16) & 0x0f);
c[12] = BsonUtils.ToHexChar((_b >> 12) & 0x0f);
c[13] = BsonUtils.ToHexChar((_b >> 8) & 0x0f);
c[14] = BsonUtils.ToHexChar((_b >> 4) & 0x0f);
c[15] = BsonUtils.ToHexChar(_b & 0x0f);
c[16] = BsonUtils.ToHexChar((_c >> 28) & 0x0f);
c[17] = BsonUtils.ToHexChar((_c >> 24) & 0x0f);
c[18] = BsonUtils.ToHexChar((_c >> 20) & 0x0f);
c[19] = BsonUtils.ToHexChar((_c >> 16) & 0x0f);
c[20] = BsonUtils.ToHexChar((_c >> 12) & 0x0f);
c[21] = BsonUtils.ToHexChar((_c >> 8) & 0x0f);
c[22] = BsonUtils.ToHexChar((_c >> 4) & 0x0f);
c[23] = BsonUtils.ToHexChar(_c & 0x0f);
return new string(c);
} // explicit IConvertible implementation
TypeCode IConvertible.GetTypeCode()
{
return TypeCode.Object;
} bool IConvertible.ToBoolean(IFormatProvider provider)
{
throw new InvalidCastException();
} byte IConvertible.ToByte(IFormatProvider provider)
{
throw new InvalidCastException();
} char IConvertible.ToChar(IFormatProvider provider)
{
throw new InvalidCastException();
} DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
throw new InvalidCastException();
} decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException();
} double IConvertible.ToDouble(IFormatProvider provider)
{
throw new InvalidCastException();
} short IConvertible.ToInt16(IFormatProvider provider)
{
throw new InvalidCastException();
} int IConvertible.ToInt32(IFormatProvider provider)
{
throw new InvalidCastException();
} long IConvertible.ToInt64(IFormatProvider provider)
{
throw new InvalidCastException();
} sbyte IConvertible.ToSByte(IFormatProvider provider)
{
throw new InvalidCastException();
} float IConvertible.ToSingle(IFormatProvider provider)
{
throw new InvalidCastException();
} string IConvertible.ToString(IFormatProvider provider)
{
return ToString();
} object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
switch (Type.GetTypeCode(conversionType))
{
case TypeCode.String:
return ((IConvertible)this).ToString(provider);
case TypeCode.Object:
if (conversionType == typeof(object) || conversionType == typeof(ObjectId))
{
return this;
}
if (conversionType == typeof(BsonObjectId))
{
return new BsonObjectId(this);
}
if (conversionType == typeof(BsonString))
{
return new BsonString(((IConvertible)this).ToString(provider));
}
break;
} throw new InvalidCastException();
} ushort IConvertible.ToUInt16(IFormatProvider provider)
{
throw new InvalidCastException();
} uint IConvertible.ToUInt32(IFormatProvider provider)
{
throw new InvalidCastException();
} ulong IConvertible.ToUInt64(IFormatProvider provider)
{
throw new InvalidCastException();
}
}
}
.NET生成MongoDB中的主键ObjectId的更多相关文章
- 分布式系统中我们会对一些数据量大的业务进行分拆,分布式系统中唯一主键ID的生成问题
分布式全局唯一ID生成策略 https://www.cnblogs.com/vandusty/p/11462585.html 一.背景 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订 ...
- Transactional Replication2:在Subscriber中,主键列是只读的
在使用Transactional Replication时,Subscriber 被认为是“Read-Only”的 , All data at the Subscriber is “read-only ...
- Hibernate 表映射 主键生成策略与复合主键
主要分析三点: 一.数据表和Java类的映射 : 二.单一主键映射和主键的生成策略 : 三.复合主键的表映射 : 一.数据表和Java类的映射 Hibernate封装了数据库DDL语句,只需要将数据 ...
- hibernate 联合主键生成机制(组合主键XML配置方式)
hibernate 联合主键生成机制(组合主键XML配置方式) 如果数据库中用多个字段而不仅仅是一个字段作为主键,也就是联合主键,这个时候就可以使用hibernate提供的联合主键生成策略. 具体 ...
- InnoDB中没有主键是如何运转的
本文章翻译自 https://blog.jcole.us/2013/05/02/how-does-innodb-behave-without-a-primary-key/ 原文作者的创作背景 一个下午 ...
- 深入理解Redis中的主键失效及其实现机制
参考:http://blog.sina.com.cn/s/articlelist_1221155353_0_1.html 作为一种定期清理无效数据的重要机制,主键失效存在于大多数缓存系统中,Reids ...
- InnoDB一定会在索引中加上主键吗
InnoDB一定会在索引中加上主键吗 http://www.penglixun.com/tech/database/will_innodb_store_pk_in_index.html
- MySQL中的主键,外键有什么作用详解
MySQL中的主键,外键有什么作用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学关系型数据库的同学,尤其在学习主键和外键时会产生一定的困惑.那么今天我们就把这个困惑连根拔起 ...
- MySQL中的主键约束和外键约束
1.主键约束 表通常具有包含唯一标识表中每一行的值的一列或一组列. 这样的一列或多列称为表的主键 (PK),用于强制表的实体完整性. 由于主键约束可保证数据的唯一性,因此经常对标识列定义这种约束. 如 ...
- Java中实现MongoDB自增主键ID
1.了解MongoDB的ObjectId MongoDB的文档固定是使用“_id”作为主键的,它可以是任何类型的,默认是个ObjectId对象(在Java中则表现为字符串),那么为什么M ...
随机推荐
- 20192305 王梓全Python程序设计实验四报告
20192305 王梓全Python程序设计实验四报告 课程:<Python程序设计> 班级: 1923 姓名: 王梓全 学号:20192305 实验教师:王志强 实验日期:2021年6月 ...
- 如何使用autotools/automake自动生成Makefile文件
前言: Linux下编程时,为了方便编译,往往使用Makefile文件自动完成编译,但是Makefile文件本身的书写十分复杂,规则很多.好在Linux为我们提供了自动生成功能完善的Makefile文 ...
- vins-fusion(1)安装编译
https://github.com/HKUST-Aerial-Robotics/VINS-Fusion https://blog.csdn.net/haner27/article/details/1 ...
- 面向对象1(Java)
什么是面向对象 面向对象编程(oop) 面向对象编程的本质是:以类的方式组织代码,以对象的组织(封装)数据 抽象 三大特征:封装.继承.多态 从认识论角度考虑是先有对象后有类.对象是具体的事物.类是抽 ...
- Spring-IoC中Set和构造器注入
新建Maven工程 修改pom文件 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project x ...
- 解决Z490-A吹雪安装macOS Monterey随机重启
1.目前发现随机重启问题是板载网卡I225-v导致,需要去除以往的网卡的kext补丁: 2.去除补丁后发现网络连接识别成功,但是无法上网:这是因为网卡ID注入错误.需要将网卡ID设置为:F315868 ...
- 几行python代码完美操控手机
最近一直成谜于python代码带来的便利,今天打算学习下用python代码来控制操作手机,首先需要利用adb,通过安卓调试桥来达到目的,其实也可以用appium来实现,不过appium多数用在自动化测 ...
- Linux中/etc目录下passwd和shadow文件
/etc/passwd介绍 首先,通过cat /etc/passwd 来查看文件/etc/passwd中内容: root:x:0:0:root:/root:/bin/bash daemon:x:1:1 ...
- NOIP2009普及组
T3]细胞分裂 [算法]数论 [题解]均分的本质是A整除B,A整除B等价于A的质因数是B的子集. 1.将m1分解质因数,即m1=p1^a1*p2^a2*...*pk^ak 所以M=m1^m2=p1^( ...
- vue中router.resolve
resolve是router的一个方法, 返回路由地址的标准化版本.该方法适合编程式导航. let router = this.$router.resolve({ path: '/home', que ...