.net 除了添加IEnumerable外,如何获取导致的差异?
我使用来检查内存中的.net 除了添加IEnumerable外,如何获取导致的差异?,.net,vb.net,linq,linq-to-objects,.net,Vb.net,Linq,Linq To Objects,我使用来检查内存中的DataTable是否与数据库中的表同步 背景是:此数据表和其他常用表存储在Web应用程序的缓存中。但与此同时,我确信这不是一个好方法,因为它是难以复制/调试的严重错误的来源 因此,我创建了一个函数来检查数据库和内存是否同步,否则将创建一个错误日志。这很好用。如果内存中有一行不在数据库中,该行将显示在“数据库中的差异”下面,反之亦然。但是,如果两个数据源(PKidRMA)中都存在行,并且某些值不同,那么日志将包含两个版本的此行(在“数据库差异”和“数据库差异”下面)。第一眼就
DataTable
是否与数据库中的表同步
背景是:此数据表
和其他常用表存储在Web应用程序的缓存
中。但与此同时,我确信这不是一个好方法,因为它是难以复制/调试的严重错误的来源
因此,我创建了一个函数来检查数据库和内存是否同步,否则将创建一个错误日志。这很好用。如果内存中有一行不在数据库中,该行将显示在“数据库中的差异”下面,反之亦然。但是,如果两个数据源(PKidRMA
)中都存在行,并且某些值不同,那么日志将包含两个版本的此行(在“数据库差异”和“数据库差异”下面)。第一眼就看出这些差异并不容易
Q:除了认为第一个序列不在第二个序列中之外,是否可以只选择导致的属性
这是完整功能的基础(第一行相关):
注意:我可以比较所有属性,但我想知道是否有更简单的(LINQ)方法。基本上,我正在寻找一种LINQ方法,只获取两个匿名类型序列的差异(因为我只选择DataRow的相关列进行比较)
编辑:我假设我必须在primarykey(idRMA
)上同时加入这两个选项,但如何选择差异?如果联接没有返回结果,则该ID在第二个序列中不存在,可以记录所有属性。但是,如果在第二个序列中有一个适当的记录,我如何选择不同的属性呢
Dim diff = From rmaMem In notInMemory
Join rmaDB In notInDatabase
On rmaMem.IdRMA Equals rmaDB.IdRMA
Select ...... ' i only want to select the properties in `rmaMem` that are different in `rmaDB` '
我认为您需要创建一个自定义的相等比较器,如下所述。最终,您必须以某种方式比较属性值,因为您使用的是Except()
,所以可以保持一致性并创建自定义比较器
除此之外,您还可以编写一个单独的函数来完成这项工作。重要的是你喜欢什么
编辑:
这是一段非常粗糙的代码,但希望能帮助您:
class Program
{
static void Main(string[] args)
{
var p1 = new Person();
p1.Name = "A";
p1.Age = 23;
var p2 = new Person();
p2.Name = "Ralph";
p2.Age = 56;
Diff(p1, p2);
}
private static void Diff(Person p1, Person p2)
{
var prop = p1.GetType().GetProperties();
var notMatchingProperties = new List<string>();
foreach(var p in prop)
{
var propName = p.Name;
var propValue1 = p1.GetType().GetProperty(propName).GetValue(p1, null);
var propValue2 = p2.GetType().GetProperty(propName).GetValue(p2, null);
if (!propValue1.Equals(propValue2))
{
notMatchingProperties.Add(propName);
}
}
foreach (var notMatchingProperty in notMatchingProperties)
{
Console.WriteLine(notMatchingProperty);
}
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
var p1=新人();
p1.Name=“A”;
p1.年龄=23岁;
var p2=新人();
p2.Name=“拉尔夫”;
p2.年龄=56岁;
差异(p1,p2);
}
私人静态空隙差异(人员p1、人员p2)
{
var prop=p1.GetType().GetProperties();
var notMatchingProperties=新列表();
foreach(道具中的var p)
{
变量propName=p.名称;
var propValue1=p1.GetType().GetProperty(propName).GetValue(p1,null);
var propValue2=p2.GetType().GetProperty(propName).GetValue(p2,null);
如果(!propValue1.等于(propValue2))
{
notMatchingProperties.Add(propName);
}
}
foreach(notMatchingProperties中的var notMatchingProperty)
{
Console.WriteLine(notMatchingProperty);
}
}
}
公共阶层人士
{
公共字符串名称{get;set;}
公共整数{get;set;}
}
我不是反射专家,所以如果其他人能对我的代码发表评论,那就太好了
最后,我不确定缓存数据是否是这里最好的方法。您可能需要考虑将信息存储在数据库中。缓存的问题是,在任何时候,网站都可能被回收(或重新启动),您可能会丢失内存中的数据
将数据保存在数据库中的另一个好处是,您可以直接在数据库上运行查询,以了解哪些属性已更改。在您看来,这就是我要做的-在数据库中创建一个表来存储缓存中的信息。我认为您需要创建一个自定义的相等比较器,如前所述。最终,您必须以某种方式比较属性值,因为您使用的是Except()
,所以可以保持一致性并创建自定义比较器
除此之外,您还可以编写一个单独的函数来完成这项工作。重要的是你喜欢什么
编辑:
这是一段非常粗糙的代码,但希望能帮助您:
class Program
{
static void Main(string[] args)
{
var p1 = new Person();
p1.Name = "A";
p1.Age = 23;
var p2 = new Person();
p2.Name = "Ralph";
p2.Age = 56;
Diff(p1, p2);
}
private static void Diff(Person p1, Person p2)
{
var prop = p1.GetType().GetProperties();
var notMatchingProperties = new List<string>();
foreach(var p in prop)
{
var propName = p.Name;
var propValue1 = p1.GetType().GetProperty(propName).GetValue(p1, null);
var propValue2 = p2.GetType().GetProperty(propName).GetValue(p2, null);
if (!propValue1.Equals(propValue2))
{
notMatchingProperties.Add(propName);
}
}
foreach (var notMatchingProperty in notMatchingProperties)
{
Console.WriteLine(notMatchingProperty);
}
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
类程序
{
静态void Main(字符串[]参数)
{
var p1=新人();
p1.Name=“A”;
p1.年龄=23岁;
var p2=新人();
p2.Name=“拉尔夫”;
p2.年龄=56岁;
差异(p1,p2);
}
私人静态空隙差异(人员p1、人员p2)
{
var prop=p1.GetType().GetProperties();
var notMatchingProperties=新列表();
foreach(道具中的var p)
{
变量propName=p.名称;
var propValue1=p1.GetType().GetProperty(propName).GetValue(p1,null);
var propValue2=p2.GetType().GetProperty(propName).GetValue(p2,null);
如果(!propValue1.等于(propValue2))
{
notMatchingProperties.Add(propName);
}
}
foreach(notMatchingProperties中的var notMatchingProperty)
{
Console.WriteLine(notMatchingProperty);
}
}
}
公共阶层人士
{
公共字符串名称{get;set;}
公共整数{get;set;}
}
我不是反射专家,所以如果其他人能对我的代码发表评论,那就太好了
最后,我不确定缓存数据是否是这里最好的方法。
Public Shared Sub CheckRmaMemoryInSyncWithDB()
Dim inSyncText As String
Dim color As Drawing.Color
Dim isInSync As Boolean
Dim daRma As New ERPModel.dsRMATableAdapters.RMATableAdapter
Dim tblRma = daRma.GetData()
Dim memory = (From rma In dsRMA.RMA
Where Not rma.IsfiChargeNull
Select rma.IdRMA, rma.fiCharge, rma.IMEI, rma.RMA_Number, rma.ModelID, rma.fiCustomer, SI_DPY = If(rma.IsSI_DPYNull, String.Empty, rma.SI_DPY), rma.fiStatus, rma.HasErrors).ToList
Dim dataBase = (From rma In tblRma
Where Not rma.IsfiChargeNull
Select rma.IdRMA, rma.fiCharge, rma.IMEI, rma.RMA_Number, rma.ModelID, rma.fiCustomer, SI_DPY = If(rma.IsSI_DPYNull, String.Empty, rma.SI_DPY), rma.fiStatus, rma.HasErrors).ToList
Dim memoryDiff = memory.Except(dataBase).ToList
Dim databaseDiff = dataBase.Except(memory).ToList
If memoryDiff.Any OrElse databaseDiff.Any Then
isInSync = False
inSyncText = "Database and Memory are NOT in Sync! Error-Log created."
Dim ex As New Exception("Database and Memory are NOT in Sync!")
Dim errInfo As String = String.Empty
'following joins both sequences to detect differences
'note: completely missing RMA's will be detected later
Dim diff = From rmaMem In memoryDiff
Join rmaDB In databaseDiff
On rmaMem.IdRMA Equals rmaDB.IdRMA
Select rmaDB.IdRMA _
, fiCharge = If(rmaMem.fiCharge = rmaDB.fiCharge, "equal", String.Format("{0}/{1}", rmaMem.fiCharge, rmaDB.fiCharge)) _
, IMEI = If(rmaMem.IMEI = rmaDB.IMEI, "equal", String.Format("{0}/{1}", rmaMem.IMEI, rmaDB.IMEI)) _
, RMA_Number = If(rmaMem.RMA_Number = rmaDB.RMA_Number, "equal", String.Format("{0}/{1}", rmaMem.RMA_Number, rmaDB.RMA_Number)) _
, ModelID = If(rmaMem.ModelID = rmaDB.ModelID, "equal", String.Format("{0}/{1}", rmaMem.ModelID, rmaDB.ModelID)) _
, fiCustomer = If(rmaMem.fiCustomer = rmaDB.fiCustomer, "equal", String.Format("{0}/{1}", rmaMem.fiCustomer, rmaDB.fiCustomer)) _
, SI_DPY = If(rmaMem.SI_DPY = rmaDB.SI_DPY, "equal", String.Format("{0}/{1}", rmaMem.SI_DPY, rmaDB.SI_DPY)) _
, fiStatus = If(rmaMem.fiStatus = rmaDB.fiStatus, "equal", String.Format("{0}/{1}", rmaMem.fiStatus, rmaDB.fiStatus)) _
, HasErrors = If(rmaMem.HasErrors = rmaDB.HasErrors, "equal", String.Format("{0}/{1}", rmaMem.HasErrors, rmaDB.HasErrors))
If diff.Any Then
errInfo &= "Differences(memory/database):" & Environment.NewLine
errInfo &= String.Join(Environment.NewLine, diff) & Environment.NewLine
End If
Dim memoryIDs = (From rma In memory
Select rma.IdRMA).ToList
Dim databaseIDs = (From rma In dataBase
Select rma.IdRMA).ToList
Dim missingInMemory = databaseIDs.Except(memoryIDs)
Dim missingInDB = memoryIDs.Except(databaseIDs)
If missingInMemory.Any Then
Dim rmaInfo = From rma In dataBase
Join idRMA In missingInMemory
On idRMA Equals rma.IdRMA
Select rma
errInfo &= "Missing RMA's in memory:" & Environment.NewLine
errInfo &= String.Join(Environment.NewLine, rmaInfo) & Environment.NewLine
End If
If missingInDB.Any Then
Dim rmaInfo = From rma In memory
Join idRMA In missingInDB
On idRMA Equals rma.IdRMA
Select rma
errInfo &= "Missing RMA's in database:" & Environment.NewLine
errInfo &= String.Join(Environment.NewLine, rmaInfo)
End If
ErrorLog.WriteError(ex, errInfo)
Else
isInSync = True
inSyncText = "Database and Memory are in Sync, all RMA's are identical in both."
End If
Dim master = DirectCast(DirectCast(HttpContext.Current.CurrentHandler, Page).Master, ERPMaster)
color = If(isInSync, Drawing.Color.Green, Drawing.Color.Red)
master.showStatusMessage(inSyncText, True, color)
End Sub
Differences(memory/database):
{ IdRMA = 25878, fiCharge = equal, IMEI = equal, RMA_Number = equal, ModelID = equal, fiCustomer = equal, SI_DPY = 1207-1104/1206-1105, fiStatus = equal, HasErrors = equal }
Missing RMA's in database:
{ IdRMA = 25882, fiCharge = 1416, IMEI = 004401076362330, RMA_Number = RMA0022725, ModelID = 449, fiCustomer = 49, SI_DPY = , fiStatus = 17, HasErrors = False }
{ IdRMA = 25881, fiCharge = 1416, IMEI = 359419030480338, RMA_Number = RMA0022724, ModelID = 758, fiCustomer = 49, SI_DPY = 1207-1124, fiStatus = 18, HasErrors = False }