Hololens项目(2) 获取业务数据

8 篇文章 0 订阅
6 篇文章 0 订阅

一、实体类代码共用

以前没找到合适的方式(也可能是因为那时时间有限)不同平台共用相同代码,同时想共用全部代码。

最后,直接将底层类库的代码拷贝到Unity中了。



好几种#if !!!

接下来还是要把这些代码放到dll中,在服务端和客户端之间共用。

因为已经过了一段时间了,dll中的代码和unity中的代码都独自修改了一些,现在先把Unity中的代码放到dll中,下一步再看是否需要将dll中的代码合并进来。

也就是要独立建立类库项目,拷贝Unity中的文件到项目中,生成dll到Plugins文件夹中。

1.方案一

将所有代码直接放到一个类库项目中


生成可以生成,但是预编译头相关的不能用了。而且,通信啊,文件处理啊,相关的代码UWP、Unity、Hololens都不同。

还是只是提取实体数据类好了。

2.方案二 只将和实体数据相关的放到dll中

1.新建类库项目,2.0(只有接口的项目)或者 3.5

 设置一下预编译头,有些代码还是要通过这个过滤的


2.将代码文件从Unity文件夹中移动到类库中

3.修改类库生成位置到Unity的Plugins文件夹中


4.脚本添加测试代码,使用dll中的类。

5.打包生成SLN

6.新的dll会在Unprocessed文件夹中,在UWP的启动项目中添加该dll的引用。

 没有添加dll的引用的话,可以部署,可以运行,但是相关的代码不会执行,也不会抛出异常

后续新增的dll,在Unity打包SLN(打包位置不变)后,不会添加到项目中,但是确实有拷贝到Unprocessed文件夹中。


手动添加到项目中,修改属性,添加引用。


  要改成UnprocessedFile(和其他Unprocessed文件夹中的dll一样),没测试过不改会怎样。



7.部署到hololens中测试

8.问题:

 1.将一个XmlNode的扩展函数放到dll中后,打包SLN时会出现问题

 

 似乎是不识别System.Xml.XmlNode。

将扩展函数放回到Unity中就可以打包SLN了。

另外,改成不用扩展函数也是有问题的。

奇怪。

  2.打包过程SLN中会出现一些Error提示,有些API不支持,最后也能打包好。

 


反射System.Reflection,在EventHelper中;2.堆栈获取System.Diagnostics.StackTrace,在LogArg中。

定义一个HOLOLENS预编译头,将不支持的代码排除掉,或者实际没用,删除掉。






二、创建WCF服务

 实例1:获取厂家列表 =============================================

 1.更新EF(暂时打算需要哪些数据添加哪些表)


 选中t_manufacturer表


2.添加服务契约

    [ServiceContract]
    public interface IDeviceDataService
    {
        [OperationContract]
        IList<manufacturer> GetManufacturers();
    }

    public class DeviceDataService: IDeviceDataService
    {
        topviewxpEntities topviewxp = new topviewxpEntities();

        public IList<manufacturer> GetManufacturers()
        {
            IList<t_manufacturer> list= topviewxp.t_manufacturer.ToList();
            IList<manufacturer> result=new List<manufacturer>();
            foreach (t_manufacturer tManufacturer in list)
            {
                manufacturer item=new manufacturer();
                item.Id = tManufacturer.ID;
                item.Name = tManufacturer.Name;
                item.Phone = tManufacturer.Phone;
                item.Linker= tManufacturer.Link;
                item.Addr = tManufacturer.Address;
                item.Email = tManufacturer.Email;
                item.Remark = tManufacturer.Remark;
                result.Add(item);
            }
            return result;
        }
    }
manufacturer是原来U3D.Objects类库中的类,t_manufacturer是EF生成的类。 manufacturer要放到dll中,并在服务端和客户端直接公用。

3.更新服务端客户引用


修改了一下命名IWCFClient->IWCFService,WCFClient->WCFService,WCFClientFactory->WCFClient

Unity中修改:

IWCFService添加

void GetManufacturers(Action<IList<manufacturer>> callback);

WCFClient添加

public void GetManufacturers(Action<IList<manufacturer>> callback)
        {
            if (Service == null)
            {
                Log.Error("WCFClientFactory.SendData", "Client==null!!");
                return;
            }
            Service.GetManufacturers(arg =>
            {
                TaskManager.Instance.AddTask(callback, arg);
            });
        }

UWP中修改:

WCFService添加

        public async void GetManufacturers(Action<IList<manufacturer>> callback)
        {
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClientFactory.Instance.Ip);
            IList<manufacturer> result = await client.GetManufacturersAsync();
            if (callback != null)
            {
                callback(result);
            }
        }
Unity脚本中测试:

    private void TestGetManufacturers()
    {
        SendLog("WCFTest.GetManufacturers Start");
        WCFClient.Instance.GetManufacturers(data =>
        {
            try
            {
                SendLog("WCFTest.GetManufacturers End" + data.Count);
                string txt = string.Format("[{0}]:",data.Count);
                for (int i = 0; i < data.Count; i++)
                {
                    txt += data[i].Name;
                    if (i < data.Count-1)
                    {
                        txt += ";";
                    }
                }
                Write(txt);
            }
            catch (Exception ex)
            {
                WriteAsync("TestGetManufacturers:" + ex.ToString());
            }
        });
    }

实例2、获取区域列表 =====================================

应该现有的Dep类和很多其他类耦合在一起了,弄一个单独的只有区域属性的类。

1.修改类库

 1.1在Dll中创建DepInfo列,将Unity中的Dep类的属性移动到DepInfo,修改Unity中的Dep类,继承自DepInfo。

 1.2 Build SLN(可能需要处理一下不兼容的API)

2.修改服务契约

 2.0更新EF,添加t_depinfo表和t_dep_size表。


 2.1修改IDeviceDataService,添加 IList<DepInfo> GetDepInfos();

 2.2修改DeviceDataService,添加

        /// <summary>
        /// 获取区域列表
        /// </summary>
        /// <returns></returns>
        public IList<DepInfo> GetDepInfos()
        {
            string tag = "DeviceDataService.GetDepInfos";
            IList<DepInfo> result = new List<DepInfo>();
            Log.Info(tag, "Start");
            try
            {
                var list = topviewxp.t_depinfo.ToList();
                foreach (var item in list)
                {
                    result.Add(item.ConvertType());
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }

        public static DepInfo ConvertType(this t_depinfo data)
        {
            DepInfo item = new DepInfo();
            item.Id = data.DepID;
            item.Name = data.DepName;
            item.PId = data.ParentID;
            item.XPos = data.xPos ?? 0;
            item.YPos = data.yPos ?? 0;
            item.Ip = data.SvrIP;

            item.CreateTime = data.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
            item.ModifyTime= data.ModifyTime.ToString("yyyy-MM-dd HH:mm:ss");
            item.UserName = data.UserName;
            item.Time = data.Time.ToString();
            item.DeleteTime = data.DeleteTime.ToString();
            item.Remark = data.Remark;
            item.XSize = data.t_dep_size.IconWidth ?? 0;
            item.YSize = data.t_dep_size.IconHeight ?? 0;
            return item;
        }

 2.3 启动服务

3.修改客户端

 3.1 更新服务引用

3.2 修改IWCFService,添加 void GetDepInfos(Action<IList<DepInfo>> callback);

3.3 修改WCFClient,添加

        public void GetDepInfos(Action<IList<DepInfo>> callback)
        {
            if (Service == null)
            {
                Log.Error("WCFClientFactory.GetDepInfos", "Client==null!!");
                return;
            }
            Service.GetDepInfos(arg =>
            {
                TaskManager.Instance.AddTask(callback, arg);
            });
        }
 3.4 修改WCFService,添加

        public async void GetDepInfos(Action<IList<DepInfo>> callback)
        {
            string tag = "WCFService.GetDepInfos";
            ServiceClientFactory.Log(tag + " Start");
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            IList<DepInfo> result = await client.GetDepInfosAsync();
            await client.CloseAsync();
            ServiceClientFactory.Log(tag + " End Count:" + result.Count);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }
3.5 修改WCFTest,添加

 private void TestGetDepInfos()
    {
        string tag = "WCFTest.GetManufacturers";
        SendLog(tag + " Start");
        WCFClient.Instance.GetDepInfos(data =>
        {
            try
            {
                SendLog(tag + " End" + data.Count);
                string txt = string.Format("[{0}]:", data.Count);
                for (int i = 0; i < data.Count; i++)
                {
                    txt += data[i].Name;
                    if (i < data.Count - 1)
                    {
                        txt += ";";
                    }
                }
                Write(txt);
            }
            catch (Exception ex)
            {
                WriteAsync(tag + ":" + ex.ToString());
            }
        });
    }
4.测试

 4.1 确认Wifi连接,确认WCF通信正常。

4.2 生成部署。

4.3 运行测试,获取数据。

因为考虑到已经有RoomInfo了,改名为DepEntity,RoomEntity

实例3、获取机房列表 =========================================

1.修改类库

 1.1 创建RoomEntity,生成dll,修改Room

 1.2 Build SLN(可能需要处理一下不兼容的API)

2.修改服务契约

 2.0 更新EF,添加T_MachineRoomInfo表和T_MachineRoomInfo_2D表和t_Dmt_Dev_Property表(机房2D图标信息?)。

 机房的位置信息存储在t_Dmt_Dev_Property中,而数据库中又没有关联起来(应该是t_Dmt_Dev_Property中又存了设备的位置信息吧,不懂,但是至少这里数据库设计时不合理的)。

 手动添加关联关系

 

单方向的


2.1修改IDeviceDataService,添加 IList<DepInfo> GetDepInfos();

2.2修改DeviceDataService,添加

 

        /// <summary>
        /// 获取区域列表
        /// </summary>
        /// <returns></returns>
        public IList<RoomEntity> GetRooms()
        {
            string tag = "DeviceDataService.GetRooms";
            IList<RoomEntity> result = new List<RoomEntity>();
            Log.Info(tag, "Start");
            try
            {
                var list = topviewxp.T_MachineRoomInfo.ToList();
                foreach (var item in list)
                {
                    result.Add(item.ConvertType());
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }
public static RoomEntity ConvertType(this T_MachineRoomInfo data)
        {
            RoomEntity item = new RoomEntity();
            item.Id = data.RoomID;
            item.Name = data.RoomName;
            item.PId = data.PID;
            item.Remark = data.Remark;
            item.PName = data.ImageName;
            item.ImageText = data.ImageText;

            item.ZoomCan = data.Cli.NullableToString();
            item.ZoomScale = data.OptimumPercent.NullableToString();
            if (data.t_Dmt_Dev_Property != null)
            {
                item.XPos = data.t_Dmt_Dev_Property.xPos ?? 0;
                item.YPos = data.t_Dmt_Dev_Property.yPos ?? 0;
                item.XSize = data.t_Dmt_Dev_Property.IconWidth ?? 0;
                item.YSize = data.t_Dmt_Dev_Property.IconHeight ?? 0;
            }

            item.Bearing = data.Obligate5;//负载
            item.Obligate3 = data.Obligate3.NullableToString();
            item.Obligate4 = data.Obligate4.NullableToString();
            item.Obligate5 = data.Obligate5;
            return item;
        }

        public static string NullableToString<T>(this Nullable<T> data) where T :struct 
        {
            return data == null ? "0" : data.ToString();
        }

 2.3 启动服务

有问题:

 添加玩后一开始保存可以,T_MachineRoomInfo中也会有一个t_Dmt_Dev_Property 属性

public virtual t_Dmt_Dev_Property t_Dmt_Dev_Property { get; set; }

但是后来发现错误列表中会有一个

Severity	Code	Description	Project	File	Line	Suppression State
Error		Error 3027: No mapping specified for the following EntitySet/AssociationSet - T_MachineRoomInfot_Dmt_Dev_Property.	WCFServiceLib	D:\SoftwareProjects\Hololens\UnityProjects\Hololens\VSProjects\WCF\WCFServiceLib\TopviewxpSevices\TopviewxpModel.edmx	272	

 运行后会出异常

System.Data.Entity.Core.EntityCommandCompilationException: An error occurred while preparing the command definition. See the inner exception for details. ---> System.Data.Entity.Core.MappingException: 
TopviewxpSevices.TopviewxpModel.msl(3,4) : error 3027: No mapping specified for the following EntitySet/AssociationSet - T_MachineRoomInfot_Dmt_Dev_Property.
   在 System.Data.Entity.Core.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedGenerateViews(EntityContainerMapping entityContainerMap, Dictionary`2 resultDictionary)
   在 System.Data.Entity.Core.Mapping.StorageMappingItemCollection.ViewDictionary.SerializedGetGeneratedViews(EntityContainer container)
   在 System.Data.Entity.Core.Common.Utils.Memoizer`2.Result.GetValue()
   在 System.Data.Entity.Core.Common.Utils.Memoizer`2.Evaluate(TArg arg)
   在 System.Data.Entity.Core.Mapping.StorageMappingItemCollection.ViewDictionary.GetGeneratedView(EntitySetBase extent, MetadataWorkspace workspace, StorageMappingItemCollection storageMappingItemCollection)
   在 System.Data.Entity.Core.Metadata.Edm.MetadataWorkspace.GetGeneratedView(EntitySetBase extent)
   在 System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.ExpandView(ScanTableOp scanTableOp, IsOfOp& typeFilter)
   在 System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.ProcessScanTable(Node scanTableNode, ScanTableOp scanTableOp, IsOfOp& typeFilter)
   在 System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Visit(ScanTableOp op, Node n)
   在 System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n)
   在 System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitRelOpDefault(RelOp op, Node n)
   在 System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Visit(ProjectOp op, Node n)
   在 System.Data.Entity.Core.Query.PlanCompiler.SubqueryTrackingVisitor.VisitChildren(Node n)
   在 System.Data.Entity.Core.Query.InternalTrees.BasicOpVisitorOfNode.VisitDefault(Node n)
   在 System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Process(Dictionary`2& tvfResultKeys)
   在 System.Data.Entity.Core.Query.PlanCompiler.PreProcessor.Process(PlanCompiler planCompilerState, StructuredTypeInfo& typeInfo, Dictionary`2& tvfResultKeys)
   在 System.Data.Entity.Core.Query.PlanCompiler.PlanCompiler.Compile(List`1& providerCommands, ColumnMap& resultColumnMap, Int32& columnCount, Set`1& entitySets)
   在 System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver, BridgeDataReaderFactory bridgeDataReaderFactory, ColumnMapFactory columnMapFactory)
   --- 内部异常堆栈跟踪的结尾 ---
   在 System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver, BridgeDataReaderFactory bridgeDataReaderFactory, ColumnMapFactory columnMapFactory)
   在 System.Data.Entity.Core.EntityClient.Internal.EntityProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree, DbInterceptionContext interceptionContext)
   在 System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.CreateCommandDefinition(ObjectContext context, DbQueryCommandTree tree)
   在 System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlanFactory.Prepare(ObjectContext context, DbQueryCommandTree tree, Type elementType, MergeOption mergeOption, Boolean streaming, Span span, IEnumerable`1 compiledQueryParameters, AliasGenerator aliasGenerator)
   在 System.Data.Entity.Core.Objects.EntitySqlQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   在 System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
   在 System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   在 System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
   在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
   在 System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   在 System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
   在 System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
   在 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   在 WCFServiceLib.DeviceDataServices.DeviceDataService.GetRooms() 位置 D:\SoftwareProjects\Hololens\UnityProjects\Hololens\VSProjects\WCF\WCFServiceLib\DeviceDataServices\DeviceDataService.cs:行号 98

不修改EF关系表,改为手动用代码获取。改为

/// <summary>
        /// 获取区域列表
        /// </summary>
        /// <returns></returns>
        public IList<RoomEntity> GetRooms()
        {
            string tag = "DeviceDataService.GetRooms";
            IList<RoomEntity> result = new List<RoomEntity>();
            Log.Info(tag, "Start");
            try
            {
                var list = from room in topviewxp.T_MachineRoomInfo
                    join posinfo in topviewxp.t_Dmt_Dev_Property on room.RoomID equals posinfo.DevID
                    select new {Room=room, PosInfo=posinfo};
                foreach (var item in list)
                {
                    RoomEntity entity = item.Room.ConvertType();
                    entity.SetRoomPostInfo(item.PosInfo);
                    result.Add(entity);
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }
        public static void SetRoomPostInfo(this RoomEntity item, t_Dmt_Dev_Property posInfo)
        {
            if (posInfo != null)
            {
                item.XPos = posInfo.xPos ?? 0;
                item.YPos = posInfo.yPos ?? 0;
                item.XSize = posInfo.IconWidth ?? 0;
                item.YSize = posInfo.IconHeight ?? 0;
            }
        }

        public static RoomEntity ConvertType(this T_MachineRoomInfo data)
        {
            RoomEntity item = new RoomEntity();
            item.Id = data.RoomID;
            item.Name = data.RoomName;
            item.PId = data.PID;
            item.Remark = data.Remark;
            item.PName = data.ImageName;
            item.ImageText = data.ImageText;
            item.ZoomCan = data.Cli.NullableToString();
            item.ZoomScale = data.OptimumPercent.NullableToString();
            item.Bearing = data.Obligate5;//负载
            item.Obligate3 = data.Obligate3.NullableToString();
            item.Obligate4 = data.Obligate4.NullableToString();
            item.Obligate5 = data.Obligate5;
            return item;
        }


这里用LINQ做了个关联查询,应该比下面的在循环中每次都查询效率高:

                var list = topviewxp.T_MachineRoomInfo.ToList();
                foreach (var item in list)
                {
                    RoomEntity entity = item.ConvertType();
                    t_Dmt_Dev_Property posInfo = topviewxp.t_Dmt_Dev_Property.Find(item.RoomID);
                    entity.SetRoomPostInfo(posInfo);
                    result.Add(entity);
                }

其实现在位置信息并没用,可以忽略,但是如果有其他有用的关联信息可以采用这种方式。


3.修改客户端

 3.1 更新服务引用

3.2 修改IWCFService,添加 void GetRooms(Action<IList<RoomEntity>> callback);

3.3 修改WCFClient,添加

        public void GetRooms(Action<IList<RoomEntity>> callback)
        {
            if (Service == null)
            {
                Log.Error("WCFClientFactory.GetRooms", "Client==null!!");
                return;
            }
            Service.GetRooms(arg =>
            {
                TaskManager.Instance.AddTask(callback, arg);
            });
        }
 3.4 修改WCFService,添加

        public async void GetRooms(Action<IList<RoomEntity>> callback)
        {
            string tag = "WCFService.GetRooms";
            ServiceClientFactory.Log(tag + " Start");
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            IList<RoomEntity> result = await client.GetRoomsAsync();
            await client.CloseAsync();
            ServiceClientFactory.Log(tag + " End Count:" + result.Count);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }
3.5 修改WCFTest,添加

    private void TestGetRooms()
    {
        string tag = "WCFTest.GetRooms";
        SendLog(tag + " Start");
        WCFClient.Instance.GetRooms(data =>
        {
            try
            {
                SendLog(tag + " End" + data.Count);
                Write(GetListText(data,"Rooms"));
            }
            catch (Exception ex)
            {
                WriteAsync(tag + ":" + ex.ToString());
            }
        });
    }

    public static string GetListText<T>(IList<T> data,string title) where T : IObject
    {
        string txt = string.Format("title[{0}]:", data.Count);
        for (int i = 0; i < data.Count; i++)
        {
            txt += data[i].Name;
            if (i < data.Count - 1)
            {
                txt += ";";
            }
        }
        return txt;
    }
4.测试

 4.1 确认Wifi连接,确认WCF通信正常。

4.2 生成部署。

4.3 运行测试,获取数据。

实例4.1、获取机房设备列表(包括设备和机柜) ==================================

1.修改类库

 1.1 创建RoomDevEntity,生成dll,修改RoomDev

 1.2 Build SLN(可能需要处理一下不兼容的API)

2.修改服务契约

 2.0更新EF,添加T_RoomDevInfo表

 2.1修改IDeviceDataService,添加 IList<RoomDevEntity> GetRoomDevs(string roomId);

 2.2修改DeviceDataService,添加

               public IList<RoomDevEntity> GetRoomDevs(string roomId)
        {
            string tag = "DeviceDataService.GetRoomDevs";
            IList<RoomDevEntity> result = new List<RoomDevEntity>();
            Log.Info(tag, "Start");
            try
            {
                var list = topviewxp.T_RoomDevInfo.Where(i => i.RoomID == roomId);
                foreach (var item in list)
                {
                    result.Add(item.ConvertType());
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }

        public static RoomDevEntity ConvertType(this T_RoomDevInfo data)
        {
            RoomDevEntity item = new RoomDevEntity();
            item.Id = data.DevID;
            item.Name = data.DevName;
            item.PId = data.RoomID;
            item.Type = data.Type.NullableToString();
            item.XPos = data.xPos ?? 0;
            item.YPos = data.yPos ?? 0;
            item.XSize = data.xSize ?? 0;
            item.YSize = data.ySize ?? 0;

            item.ZoomCan = data.Cli ?? 0;
            item.State = data.State.NullableToString();

            //下面这些不确定,细节可能要调整
            item.Pos = data.Obligate3;
            item.Obligate4 = data.Obligate4;
            item.Power = data.Obligate5;
            return item;
        }

  2.3 启动服务

3.修改客户端

 3.1 更新服务引用

3.2 修改IWCFService,添加 void GetRoomDevs(string roomId,Action<IList<RoomDevEntity>> callback);

3.3 修改WCFClient,添加

        public void GetRoomDevs(string roomId, Action<IList<RoomDevEntity>> callback)
        {
            if (Service == null)
            {
                Log.Error("WCFClientFactory.GetRoomDevs", "Client==null!!");
                return;
            }
            Service.GetRoomDevs(roomId,arg =>
            {
                TaskManager.Instance.AddTask(callback, arg);
            });
        }
 3.4 修改WCFService,添加

        public async void GetRoomDevs(string roomId,Action<IList<RoomDevEntity>> callback)
        {
            string tag = "WCFService.GetRooms";
            ServiceClientFactory.Log(tag + " Start");
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            IList<RoomDevEntity> result = await client.GetRoomDevsAsync(roomId);
            await client.CloseAsync();
            ServiceClientFactory.Log(tag + " End Count:" + result.Count);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }
3.5 修改WCFTest,添加

    private void TestGetRoomDevs(string roomId)
    {
        string tag = "WCFTest.GetRooms";
        SendLog(tag + " Start");
        WCFClient.Instance.GetRoomDevs(roomId,data =>
        {
            try
            {
                SendLog(tag + " End" + data.Count);
                Write(GetListText(data, "Rooms"));
            }
            catch (Exception ex)
            {
                WriteAsync(tag + ":" + ex.ToString());
            }
        });
    }

3.6 修改测试界面(因为需要选择一个机房)

4.测试

 4.1 确认Wifi连接,确认WCF通信正常。

4.2 生成部署。

4.3 运行测试,获取数据。


实例4.2、获取机柜组列表 =================================================

1.修改类库

 1.1 创建CabinetGroupEntity,生成dll,修改CabinetGroup

 1.2 Build SLN(可能需要处理一下不兼容的API)

2.修改服务契约

 2.0更新EF,添加T_EquipCabinetGroup表

 2.1修改IDeviceDataService,添加 IList<CabinetGroupEntity> GetCabinetGroups(string roomId);

 2.2修改DeviceDataService,添加

        public IList<CabinetGroupEntity> GetCabinetGroups(string roomId)
        {
            string tag = "DeviceDataService.GetCabinetGroups";
            IList<CabinetGroupEntity> result = new List<CabinetGroupEntity>();
            Log.Info(tag, "Start");
            try
            {
                var list = from roomDev in topviewxp.T_RoomDevInfo
                    join cabinetGroup in topviewxp.T_EquipCabinetGroup on roomDev.DevID equals cabinetGroup.ID
                    where roomDev.RoomID == roomId
                    select new
                    {
                        RoomDev = roomDev,
                        CabinetGroup = cabinetGroup
                    };
                foreach (var item in list)
                {
                    CabinetGroupEntity entity = item.CabinetGroup.ConvertType(item.RoomDev);
                    result.Add(entity);
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }
 
        public static CabinetGroupEntity ConvertType(this T_EquipCabinetGroup data, T_RoomDevInfo dev)
        {
            CabinetGroupEntity group=new CabinetGroupEntity();
            group.Id = data.ID;
            group.Name = dev.DevName;
            group.PId = dev.RoomID;
            group.Num = data.NodeNum ?? 0;
            group.HorOrVer = data.HorizontalOrVertical;
            group.Obligate4 = data.Obligate4;
            group.Power = 0;//机柜额定功率? 在机柜表T_EquipCabinet的Obligate6中
            group.Type = dev.Type.NullableToString();
            group.RoomDev = dev.ConvertType();//关联的机房设备
            return group;
        }

机柜组其实是一种特殊的机房设备,相当于是该机房设备的附加信息。
 2.3 启动服务

3.修改客户端

客户端这边暂时不需要直接获取机柜组列表


实例4.3、获取机柜列表 ===================================================

1.修改类库

 1.1 创建CabinetEntity,生成dll,修改Cabinet

 1.2 Build SLN(可能需要处理一下不兼容的API)

2.修改服务契约

 2.0更新EF,添加T_EquipCabinet表

 2.1修改IDeviceDataService,添加 IList<CabinetEntity> GetCabinets(string roomId);

 2.2修改DeviceDataService,添加

        public IList<CabinetEntity> GetCabinets(string roomId)
        {
            string tag = "DeviceDataService.GetCabinets";
            IList<CabinetEntity> result = new List<CabinetEntity>();
            Log.Info(tag, "Start");
            try
            {
                var list = from c in topviewxp.T_EquipCabinet
                    join cg in topviewxp.T_EquipCabinetGroup on c.PID equals cg.ID
                    join dev in topviewxp.T_RoomDevInfo on cg.ID equals dev.DevID
                    where dev.RoomID == roomId
                    select new {Cabinet = c, Group = cg, Dev = dev};
                foreach (var item in list)
                {
                    CabinetEntity entity = item.Cabinet.ConvertType(item.Group, item.Dev);
                    result.Add(entity);
                }

            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }
        public static CabinetEntity ConvertType(this T_EquipCabinet data, T_EquipCabinetGroup group,T_RoomDevInfo dev)
        {
            CabinetEntity item = new CabinetEntity();
            item.Id = data.ID;
            item.Name = data.Name;
            item.PId = data.PID;
            item.Power = data.Obligate6.ToFloat();
            item.Weight = 0;
            item.Bearing = 0;
            item.Vid = data.CabinetNum.NullableToString();
            item.Length = data.Length ?? 0;
            item.Width = data.Width ?? 0;
            item.High = data.High ?? 0;
            item.Model = data.Model;
            item.UNum = data.UNum ?? 0;
            item.OtherName = data.OtherName;
            item.K = data.Obligate3;
            item.Obligate4 = data.Obligate4.NullableToString();
            item.Obligate5 = data.Obligate5.NullableToString();
            return item;
        }

现在机柜和机柜组是1对1的关系。
  2.3 启动服务

3.修改客户端

客户端这边暂时不需要直接获取机柜列表



实例5、获取设备组(设备文件夹)列表 =====================================

1.修改类库

 1.1 将DeviceFolder放到列库中

 1.2 Build SLN(可能需要处理一下不兼容的API)

2.修改服务契约

 2.0更新EF,添加t_Folder表和t_FolderNode变

 这里有问题,发现选了也添加不上,结果到数据库一看,两个表没有主键。

将t_Folder的ID设为主键,没问题。

将t_FolderNode的NodeID设置为主键,不行,因为有重复的。

找出重复的一看,是,一个是已经删除了的(Removetime不为0)。

SELECT  NodeID FROM  t_FolderNode t WHERE NodeID IN (SELECT NodeID FROM t_FolderNode GROUP BY NodeID HAVING COUNT(NodeID)>1 ) and Removetime !=0 ORDER BY NodeID
 删除重复部分的无用数据,再设置NodeID为主键,可以。


delete from t_FolderNode where NodeID in (SELECT  NodeID FROM  t_FolderNode t WHERE NodeID IN (SELECT NodeID FROM t_FolderNode GROUP BY NodeID HAVING COUNT(NodeID)>1 ) and Removetime !=0)
 顺便设置一下外键关系

再添加到EF中,可以了


最后,删除数据库中的主键设置和关系后,并且在EF中添加一张表,仍然客户获取数据。

//todo:测试t_FolderNode表中有重复NodeID会怎样?




 2.1修改IDeviceDataService,添加 IList<DeviceFolder> GetDeviceFolders(string roomId);

 2.2修改DeviceDataService,添加

public IList<DeviceFolder> GetDeviceFolders(string roomId)
        {
            string tag = "DeviceDataService.GetCabinets";
            IList<DeviceFolder> result = new List<DeviceFolder>();
            Log.Info(tag, "Start");
            try
            {

                var list = from folder in topviewxp.t_Folder where folder.PID == roomId select folder;
                foreach (var item in list)
                {
                    DeviceFolder entity = EFEntityExtension.ConverType(item);
                    result.Add(entity);
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.Info(tag, "End:" + result.Count);
            return result;
        }
        public static DeviceFolder ConverType(this t_Folder data)
        {
            DeviceFolder item=new DeviceFolder();
            item.Id = data.ID;
            item.Name = data.Name;
            item.PId = data.PID;
            string nodeIds = "";
            foreach (t_FolderNode node in data.t_FolderNode)
            {
                nodeIds += node.NodeID + "^";
            }
            item.ChildrenIds = nodeIds;
            return item;
        }

  2.3 启动服务

3.修改客户端

 3.1 更新服务引用

3.2 修改IWCFService,添加 void GetDeviceFolders(string roomId, Action<IList<DeviceFolder>> callback)

3.3 修改WCFClient,添加

        public void GetDeviceFolders(string roomId, Action<IList<DeviceFolder>> callback)
        {
            if (Service == null)
            {
                Log.Error("WCFClientFactory.GetDeviceFolders", "Client==null!!");
                return;
            }
            Service.GetDeviceFolders(roomId, arg =>
            {
                if (TaskManager.Instance == null)
                {
                    Service.SendString("TaskManager.Instance == null!!!!!!!!");
                }
                else
                {
                    TaskManager.Instance.AddTask(callback, arg);
                }
            });
        }

 3.4 修改WCFService,添加

        public void GetDeviceFolders(string roomId, Action<IList<DeviceFolder>> callback)
        {
            string tag = "WCFService.GetRooms";
            ServiceClientFactory.Log(tag + " Start");
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            IList<DeviceFolder> result = client.GetDeviceFolders(roomId);
            client.Close();
            ServiceClientFactory.Log(tag + " End Count:" + result.Count);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }
这个是Unity中使用WCF测试用的版本

3.5 修改WCFTest,添加

    private void TestGetDeviceFolders(string roomId)
    {
        string tag = "WCFTest.GetDeviceFolders";
        SendLog(tag + " Start");
        WCFClient.Instance.GetDeviceFolders(roomId, data =>
        {
            try
            {
                SendLog(tag + " End" + data.Count);
                //Write(GetListText(data, "Rooms"));
                DeviceFolders = data;
                ShowListEx(data, DpDeviceFolders, "RoomDevs");

                if (data.Count > 0)
                {
                    Write(ObjectToString(data[0]));
                    Write("NodeCount:" + data[0].ChildrenList.Count);
                }
            }
            catch (Exception ex)
            {
                WriteAsync(tag + ":" + ex.ToString());
            }
        });
    }

实例6、获取文件夹内机房设备

1.修改服务契约

 IDeviceDataService添加:

        /// <summary>
        /// 获取设备组中的设备
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        IList<RoomDevEntity> GetRoomDevsInFolder(string folderId);

 DeviceDataService添加:

        public IList<RoomDevEntity> GetRoomDevsInFolder(string folderId)
        {
            string tag = "DeviceDataService.GetRoomDevsInGroup";
            IList<RoomDevEntity> result = new List<RoomDevEntity>();
            Log.LogStart(tag);
            try
            {
                var list = from node in topviewxp.t_FolderNode
                           join dev in topviewxp.T_RoomDevInfo on node.NodeID equals  dev.DevID
                           join cg in topviewxp.T_EquipCabinetGroup on dev.DevID equals cg.ID into cgJoin from cg2 in cgJoin.DefaultIfEmpty()
                           join cabinet in topviewxp.T_EquipCabinet on cg2.ID equals cabinet.PID into cabinetsJoin from cabinet2 in cabinetsJoin.DefaultIfEmpty()
                           where node.PID == folderId
                           orderby dev.DevName
                           select new { Dev = dev, Group = cg2, Cabinet = cabinet2 };
                string sql = list.ToString();
                foreach (var item in list)
                {
                    RoomDevEntity devEntity = item.Dev.ConvertType();
                    CabinetGroupEntity groupEntity = item.Group.ConvertType(item.Dev);
                    if (groupEntity != null)
                    {
                        CabinetEntity cabinetEntity = item.Cabinet.ConvertType(item.Group, item.Dev);
                        groupEntity.Items.Add(cabinetEntity);
                        devEntity.Group = groupEntity;
                    }
                    result.Add(devEntity);
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.LogEnd(tag, "Count:" + result.Count);
            return result;
        }


实例7、获取设备类型和模型图片对应关系

1.修改EF

 添加t_SetModel表、t_template_subtype表、t_Template_TypeStatePic表。

 t_SetModel表没有主键,将RecordID设为主键;t_Template_TypeStatePic没有主键,将TypeCode和State设为主键。

 没有主键的表无法添加到EF中

2.修改服务契约

IDeviceDataService添加

        /// <summary>
        /// 获取模型和TypeCode的对应关系
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        IList<Model> GetModelList();

DeviceDataService添加

public IList<Model> GetModelList()
        {
            string tag = "DeviceDataService.Model";
            IList<Model> result = new List<Model>();
            Log.LogStart(tag);
            try
            {
                var list1 = from devType in topviewxp.t_template_subtype
                           join typeImage in topviewxp.t_Template_TypeStatePic 
                           on new {Id= (int)devType.nType,State=0}  equals new {Id= (int)typeImage.TypeCode ,State=typeImage.State}
                    select new { Id = devType.nType, Name = devType.TypeName,Image= typeImage.DevLinkMap };
                var list2 = from model in topviewxp.t_SetModel.ToList() select new {Id = model.ID, Name = model.Name};//这里不加ToList()会很慢

                //string sql1 = list1.ToString();
                //string sql2 = list2.ToString();
                foreach (var type1 in list1)
                {
                    Model model=new Model();
                    model.Id = type1.Id.ToString();
                    string image = type1.Image;
                    image = image.Replace("_前面板_0.png", "");
                    var type2 = list2.FirstOrDefault(i => i.Id == image);
                    if (type2 != null)
                    {
                        model.Name = type2.Name;
                    }
                    else
                    {
                        model.Name = "NULL [" +type1.Name +"]";
                    }
                    result.Add(model);
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.LogEnd(tag, "Count:" + result.Count);
            return result;
        }

3.修改客户端

 3.1 更新WCFClientConsole的服务引用

3.2 从WCFClientConsole拷贝新的DeviceDataServiceClient到Unity中

3.3 修改IWCFService添加 void GetModelList(Action<IList<Model>> callback);

3.4 WCFService 添加

        public void GetModelList(Action<IList<Model>> callback)
        {
            string tag = "WCFService.GetModelList";
            ServiceClientFactory.LogStart(tag);
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            IList<Model> result = client.GetModelList();
            client.Close();
            ServiceClientFactory.LogEnd(tag,"Count:" + result.Count);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }

 3.5 脚本测试

    private void TestGetModelList()
    {
        string tag = "WCFTest.GetModelList";
        //SendLog(tag + " Start");
        WCFClient.Instance.GetModelList(data =>
        {
            try
            {
                //SendLog(tag + " End" + data.Count);
                ShowListEx(data, DpModelList, "GetModelList");
                foreach (var item in data)
                {
                    try
                    {
                        RoomInfoFactory.TypeCodeToModelName.Add(item.Id, item.Name);
                    }
                    catch (Exception ex)
                    {
                        WriteAsync(tag + ":" + ex.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                WriteAsync(tag + ":" + ex.ToString());
            }
        });
    }

三、与老的数据获取接口对接

1. 获取机房背景信息 =========================================

 1.1 修改服务契约

        /// <summary>
        /// 获取机房背景信息
        /// </summary>
        /// <param name="roomId"></param>
        /// <returns></returns>
        [OperationContract]
        string GetRoomImageText(string roomId);

        public string GetRoomImageText(string roomId)
        {
            T_MachineRoomInfo room=topviewxp.T_MachineRoomInfo.Find(roomId);
            if (room == null)
            {
                return "";
            }
            else
            {
                return room.ImageText;
            }
        }

1.2 修改客户端

IWCFService添加 void GetRoomImageText(string roomId, Action<string> callback);

WCFService添加

        public void GetRoomImageText(string roomId, Action<string> callback)
        {
            string tag = "WCFService.GetRoomImageText";
            ServiceClientFactory.Log(tag + " Start");
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            string result = client.GetRoomImageText(roomId);
            client.Close();
            ServiceClientFactory.Log(tag + " End Count:" + result.Length);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }


2.获取设备列表和机柜信息  ========================================

将机房设备、机柜组、机柜关联在一起,一起发生给客户端,为下面的创建机房做准备

 2.1.修改服务契约

 IDeviceDataService添加

        /// <summary>
        /// 获取机房设备列表(设备对象中包含机柜组、机柜数据)
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        IList<RoomDevEntity> GetRoomDevsAndCabinets(string roomId);

        public IList<RoomDevEntity> GetRoomDevsAndCabinets(string roomId)
        {
            string tag = "DeviceDataService.GetRoomDevsAndCabinets";
            IList<RoomDevEntity> result = new List<RoomDevEntity>();
            Log.LogStart(tag);
            try
            {
                var list = from dev in topviewxp.T_RoomDevInfo
                    join cg in topviewxp.T_EquipCabinetGroup on dev.DevID equals cg.ID into cgJoin from cg2 in cgJoin.DefaultIfEmpty() //left join
                    join cabinet in topviewxp.T_EquipCabinet on cg2.ID equals cabinet.PID into cabinetsJoin from cabinet2 in cabinetsJoin.DefaultIfEmpty() //left join
                    where dev.RoomID == roomId
                    orderby dev.DevName
                    select new {Dev = dev, Group = cg2, Cabinet = cabinet2 };
                //string sql = list.ToString();
                foreach (var item in list)
                {
                    RoomDevEntity devEntity = item.Dev.ConvertType();
                    CabinetGroupEntity groupEntity = item.Group.ConvertType(item.Dev);
                    if (groupEntity != null)
                    {
                        CabinetEntity cabinetEntity = item.Cabinet.ConvertType(item.Group, item.Dev);
                        groupEntity.Items.Add(cabinetEntity);
                        devEntity.Group = groupEntity;
                    }
                    result.Add(devEntity);
                }
            }
            catch (Exception ex)
            {
                Log.Error(tag, ex);
            }
            Log.LogEnd(tag, "Count:" + result.Count);
            return result;
        }


2.2.修改客户端

IWCFService添加  

 void GetRoomDevsAndCabinets(string roomId, Action<IList<RoomDevEntity>> callback);

WCFService添加

        public void GetRoomDevsAndCabinets(string roomId, Action<IList<RoomDevEntity>> callback)
        {
            string tag = "WCFService.GetRoomDevsAndCabinets";
            ServiceClientFactory.Log(tag + " Start");
            DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
            IList<RoomDevEntity> result = client.GetRoomDevsAndCabinets(roomId);
            client.Close();
            ServiceClientFactory.Log(tag + " End Count:" + result.Count);
            if (callback != null)
            {
                ServiceClientFactory.Log(tag + " callback");
                callback(result);
            }
        }


3.获取RoomInfo并创建机房

    private void TestCreateRoom(RoomEntity roomEntity)
    {
        string tag = "WCFTest.GetRoomImageText";
        SendLog(tag + " Start");
        Room room = new Room(roomEntity);//类型转换,对接以前的接口
        WCFClient.Instance.GetRoomImageText(room.Id, data =>
        {
            try
            {
                SendLog(tag + " End" + data.Length);
                RoomInfo roomInfo= SerializeHelper.LoadFromBase64Text<RoomInfo>(data, Encoding.UTF8);//背景信息RoomInfo
                Write(ObjectToString(roomInfo));
                string xml0 = SerializeHelper.GetXmlText(roomInfo);
                Log.Error("RoomInfo0:\n"+ xml0);
                WCFClient.Instance.GetRoomDevsAndCabinets(room.Id, roomDevEntitys =>
                {
                    CreateRoom(room, roomInfo, roomDevEntitys);
                });
                //WCFClient.Instance.GetAllDevsInRoom(room.Id, roomDevEntitys =>
                //{
                //    CreateRoom(room, roomInfo, roomDevEntitys);
                //});//这个可以把机柜内设备也一起创建出来
            }
            catch (Exception ex)
            {
                WriteAsync(tag + ":" + ex.ToString());
            }
        });
    }



    private void CreateRoom(Room room ,RoomInfo roomInfo,IList<RoomDevEntity> roomDevEntitys)
    {
        try
        {
            foreach (RoomDevEntity roomDevEntity in roomDevEntitys)
            {
                RoomDev roomDev = new RoomDev(roomDevEntity);//类型转换,对接以前的接口
                Log.Error("roomDev:\n" + roomDev.Name);
                room.DevList.Add(roomDev);
            }

            RoomInfoFactory.CreateRoomDevs(roomInfo, room, null);//修改RoomInfo,添加机房设备信息

            string xml1 = SerializeHelper.GetXmlText(roomInfo);
            Log.Error("RoomInfo1:\n" + xml1);

            RoomObject roomObj = new RoomObject(roomInfo);//根据RoomInfo创建机房
        }
        catch (Exception ex)
        {
            Log.Error("TestGetRoomImageText.CreateRoom", ex.ToString());
        }
    }


上面的类型转换是通过基类创建子类,基本属性的都相同。因为子类中用到的有些类解耦做的不好,无法放到类库中。如:

        public RoomDev(RoomDevEntity data)
        {
            this.Id = data.Id;
            this.PId = data.PId;
            this.Name = data.Name;
            this.Type = data.Type;
            this.XPos = data.XPos;
            this.YPos = data.YPos;
            this.XSize = data.XSize;
            this.YSize = data.YSize;
            this.ZoomCan = data.ZoomCan;
            this.State = data.State;
            this.Pos = data.Pos;
            this.Power = data.Power;

            //this.GroupType = data.GroupType;
            //this.DevType = data.DevType;
            if (data.Group != null)
            {
                this.Group=new CabinetGroup(data.Group);
            }
        }



  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值