Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 除了添加IEnumerable外,如何获取导致的差异?_.net_Vb.net_Linq_Linq To Objects - Fatal编程技术网

.net 除了添加IEnumerable外,如何获取导致的差异?

.net 除了添加IEnumerable外,如何获取导致的差异?,.net,vb.net,linq,linq-to-objects,.net,Vb.net,Linq,Linq To Objects,我使用来检查内存中的DataTable是否与数据库中的表同步 背景是:此数据表和其他常用表存储在Web应用程序的缓存中。但与此同时,我确信这不是一个好方法,因为它是难以复制/调试的严重错误的来源 因此,我创建了一个函数来检查数据库和内存是否同步,否则将创建一个错误日志。这很好用。如果内存中有一行不在数据库中,该行将显示在“数据库中的差异”下面,反之亦然。但是,如果两个数据源(PKidRMA)中都存在行,并且某些值不同,那么日志将包含两个版本的此行(在“数据库差异”和“数据库差异”下面)。第一眼就

我使用来检查内存中的
DataTable
是否与数据库中的表同步

背景是:此
数据表
和其他常用表存储在Web应用程序的
缓存
中。但与此同时,我确信这不是一个好方法,因为它是难以复制/调试的严重错误的来源

因此,我创建了一个函数来检查数据库和内存是否同步,否则将创建一个错误日志。这很好用。如果内存中有一行不在数据库中,该行将显示在“数据库中的差异”下面,反之亦然。但是,如果两个数据源(PK
idRMA
)中都存在行,并且某些值不同,那么日志将包含两个版本的此行(在“数据库差异”和“数据库差异”下面)。第一眼就看出这些差异并不容易

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 }