一、实体类代码共用
以前没找到合适的方式(也可能是因为那时时间有限)不同平台共用相同代码,同时想共用全部代码。
最后,直接将底层类库的代码拷贝到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 GetManufacturers();
}
public class DeviceDataService: IDeviceDataService
{
topviewxpEntities topviewxp = new topviewxpEntities();
public IList GetManufacturers()
{
IList list= topviewxp.t_manufacturer.ToList();
IList result=new List();
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> callback);
public void GetManufacturers(Action> 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> callback)
{
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClientFactory.Instance.Ip);
IList 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
2.2修改DeviceDataService,添加
///
/// 获取区域列表
///
///
public IList GetDepInfos()
{
string tag = "DeviceDataService.GetDepInfos";
IList result = new List();
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
3.3 修改WCFClient,添加
public void GetDepInfos(Action> 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> callback)
{
string tag = "WCFService.GetDepInfos";
ServiceClientFactory.Log(tag + " Start");
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
IList 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
2.2修改DeviceDataService,添加
///
/// 获取区域列表
///
///
public IList GetRooms()
{
string tag = "DeviceDataService.GetRooms";
IList result = new List();
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(this Nullable 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.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.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..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关系表,改为手动用代码获取。改为
///
/// 获取区域列表
///
///
public IList GetRooms()
{
string tag = "DeviceDataService.GetRooms";
IList result = new List();
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;
}
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.1 更新服务引用
3.2 修改IWCFService,添加 void GetRooms(Action
3.3 修改WCFClient,添加
public void GetRooms(Action> 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> callback)
{
string tag = "WCFService.GetRooms";
ServiceClientFactory.Log(tag + " Start");
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
IList 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(IList 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
2.2修改DeviceDataService,添加
public IList GetRoomDevs(string roomId)
{
string tag = "DeviceDataService.GetRoomDevs";
IList result = new List();
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;
}
3.修改客户端
3.1 更新服务引用
3.2 修改IWCFService,添加 void GetRoomDevs(string roomId,Action
3.3 修改WCFClient,添加
public void GetRoomDevs(string roomId, Action> 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> callback)
{
string tag = "WCFService.GetRooms";
ServiceClientFactory.Log(tag + " Start");
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
IList 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 GetCabinetGroups(string roomId)
{
string tag = "DeviceDataService.GetCabinetGroups";
IList result = new List();
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
2.2修改DeviceDataService,添加
public IList GetCabinets(string roomId)
{
string tag = "DeviceDataService.GetCabinets";
IList result = new List();
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;
}
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
2.2修改DeviceDataService,添加
public IList GetDeviceFolders(string roomId)
{
string tag = "DeviceDataService.GetCabinets";
IList result = new List();
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;
}
3.修改客户端
3.1 更新服务引用
3.2 修改IWCFService,添加 void GetDeviceFolders(string roomId, Action
3.3 修改WCFClient,添加
public void GetDeviceFolders(string roomId, Action> 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> callback)
{
string tag = "WCFService.GetRooms";
ServiceClientFactory.Log(tag + " Start");
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
IList 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添加:
///
/// 获取设备组中的设备
///
///
[OperationContract]
IList GetRoomDevsInFolder(string folderId);
DeviceDataService添加:
public IList GetRoomDevsInFolder(string folderId)
{
string tag = "DeviceDataService.GetRoomDevsInGroup";
IList result = new List();
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添加
///
/// 获取模型和TypeCode的对应关系
///
///
[OperationContract]
IList GetModelList();
DeviceDataService添加
public IList GetModelList()
{
string tag = "DeviceDataService.Model";
IList result = new List();
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
3.4 WCFService 添加
public void GetModelList(Action> callback)
{
string tag = "WCFService.GetModelList";
ServiceClientFactory.LogStart(tag);
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
IList 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 修改服务契约
///
/// 获取机房背景信息
///
///
///
[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
WCFService添加
public void GetRoomImageText(string roomId, Action 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添加
///
/// 获取机房设备列表(设备对象中包含机柜组、机柜数据)
///
///
[OperationContract]
IList GetRoomDevsAndCabinets(string roomId);
public IList GetRoomDevsAndCabinets(string roomId)
{
string tag = "DeviceDataService.GetRoomDevsAndCabinets";
IList result = new List();
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
WCFService添加
public void GetRoomDevsAndCabinets(string roomId, Action> callback)
{
string tag = "WCFService.GetRoomDevsAndCabinets";
ServiceClientFactory.Log(tag + " Start");
DeviceDataServiceClient client = ServiceClientFactory.GetDeviceDataServiceClient(WCFClient.Instance.Ip);
IList 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(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 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);
}
}