.net多語言和資料集內多資料表的處理(3) (轉)

themoney發表於2007-10-03
.net多語言和資料集內多資料表的處理(3) (轉)[@more@]
3   考慮以上兩種情況的綜合
  當以上兩種情況湊在一塊的時候,情況還會複雜一些,因為在我們的這個解決方案中,多語言和資訊的主體是採用的松耦合,如果不採用松耦合就不能保證其通用性和可擴充套件性,但是採用了松耦合在資料集中多表操作時又會產生麻煩。
  因為松耦合,所以在資料集中自動級連的時候並不能夠自動更新,修改還無所謂,我們只要保證和多語言表關聯的那個Guid不變就可以了,但是刪除呢?我們總不能把資訊主體刪除了卻又把多語言資料留著吧,更麻煩的是因為資料已經刪除,我們很難知道刪除之前與多語言資料表關聯的Guid是多少。而且我們需要把對資訊主體的刪除和多語言資料的刪除放到一個事務中,相信誰都不會希望偶然出錯資訊主體未被刪除的時候多語言資料都被刪除了。而且,我們還要實現前面曾說過的一個目標:每個都只需要維護自己用的這種語言的記錄資訊就可以了,而不用考慮其他語言的問題,也可以非常方便的即使執行了一段時間後再次新增支援的語言,不需要在新增記錄的事後就需要新增所有語言的版本,只在需要的時候才新增相應語言的版本,從而使記錄數儘量的少。
  好了,我們知道了需求,然後該怎麼做呢?看下面的程式碼:   在從資料庫獲取資料時: public AddressData GetAddress(string languageCode)   {   AddressData ds = new AddressData();     DataAdapter DARegion = new SqlDataAdapter(AddressSQL.strGetRegion,SQLConfig.DataBaseConnection);   DARegion.Fill(ds.Region);     SqlDataAdapter DACountry = new SqlDataAdapter(AddressSQL.strGetCountry,SQLConfig.DataBaseConnection);   DACountry.Fill(ds.Country);     SqlDataAdapter DAProvince = new SqlDataAdapter(AddressSQL.strGetProvince,SQLConfig.DataBaseConnection);   DAProvince.Fill(ds.Province);     SqlDataAdapter DACity = new SqlDataAdapter(AddressSQL.strGetCity,SQLConfig.DataBaseConnection);   DACity.Fill(ds.City);     SqlDataAdapter DAPort = new SqlDataAdapter(AddressSQL.strGetPort,SQLConfig.DataBaseConnection);   DAPort.Fill(ds.Port);     RegionTypeData regionTypeDS =  GetRegionType(languageCode);     foreach ( AddressData.RegionRow region in ds.Region)   {   if (!region.IsNameGuidNull())   {   region.Name = DisplayString.GetDisplay(region.NameGuid,languageCode,vDisplayTable);   }   if (regionTypeDS.RegionType.FindByRegionTypeID(region.RegionTypeID) != null)   {   region.RegionTypeName = regionTypeDS.RegionType.FindByRegionTypeID(region.RegionTypeID).Abbr;   }   }     foreach ( AddressData.CountryRow country in ds.Country)   {   if (!country.IsNameGuidNull())   {   country.Name = DBDisplayString.GetDisplay(country.NameGuid,languageCode,vDisplayTable);   }   }     foreach (AddressData.ProvinceRow province in ds.Province)   {   if (!province.IsNameGuidNull())   {   province.Name = DBDisplayString.GetDisplay(province.NameGuid,languageCode,vDisplayTable);   }   }     foreach (AddressData.CityRow city in ds.City)   {   if (!city.IsNameGuidNull())   {   city.Name = DBDisplayString.GetDisplay(city.NameGuid, languageCode,vDisplayTable);   }   }     foreach (AddressData.PortRow port in ds.Port)   {   if (!port.IsNameGuidNull())   {   port.Name = DBDisplayString.GetDisplay(port.NameGuid,languageCode,vDisplayTable);   }   }     return ds;
  }
這樣,只需要透過一個單一的Name欄位便可以獲取使用者所用語言的資料了,而不用考慮使用者使用的到底是哪一種語言。這裡不在資料庫裡直接做join的原因是:這個獲取多語言資料的方法並不是直接把資料庫資料取出來那麼簡單,假如使用者要取的那種語言的某條資料恰好沒有呢?我們取了一個系統預設語言的資料,那麼哪一種是系統預設語言呢?可見如果這些都放在SQL中做的話,要傳入的引數會非常多,SQL語句會變得非常複雜,也就不利於封裝了,而且考慮到SQL語句的複雜性,我沒有選擇這麼做。
  那麼把資料更新回資料庫又該怎麼辦呢?看下面的程式碼:   private void DeleteDisplay(AddressData ds, Guid refGuid)   {   foreach (AddressData.AddressDisStrRow dis in ds.AddressDisStr.("RefGuid = +refGuid+ "))   {   dis.Delete();   }   }   private void DeletePort(AddressData ds, int portID)   {   if (!ds.Port.FindByPortID(portID).IsNameGuidNull())   {   DeleteDisplay(ds,ds.Port.FindByPortID(portID).NameGuid);   }   ds.Port.FindByPortID(portID).Delete();   }     private void DeleteCity(AddressData ds, int cityID)   {   if (!ds.City.FindByCityID(cityID).IsNameGuidNull())   {   DeleteDisplay(ds,ds.City.FindByCityID(cityID).NameGuid);   }   foreach (AddressData.PortRow port in ds.Port)   {   if ((int)port["CityID",DataRowVersion.Original] == cityID)   {   port.RejectChanges();   DeletePort(ds,port.PortID);   }   }   ds.City.FindByCityID(cityID).Delete();   }     private void DeleteProvince(AddressData ds, int provinceID)   {   if (!ds.Province.FindByProvinceID(provinceID).IsNameGuidNull())   {   DeleteDisplay(ds,ds.Province.FindByProvinceID(provinceID).NameGuid);     }   foreach (AddressData.CityRow city in ds.City)   {   if ((int)city["ProvinceID",DataRowVersion.Original] == provinceID)   {   city.RejectChanges();   DeleteCity(ds,city.CityID);   }   }   ds.Province.FindByProvinceID(provinceID).Delete();
  }   public void UpdateProvince(AddressData ds, string languageCode)   {   SqlDataAdapter DAAddressDisStr = new SqlDataAdapter(AddressSQL.strGetAddressDisStr,SQLConfig.DataBaseConnection);   DAAddressDisStr.Fill(ds.AddressDisStr);     foreach(AddressData.ProvinceRow province in ds.Province)   {   if (province.RowState == DataRowState.Deleted)   {   province.RejectChanges();   DeleteProvince(ds,province.ProvinceID);   }   else if (province.RowState == DataRowState.Added || province.RowState == DataRowState.Modified)   {   if (province.IsNameNull() && !province.IsNameGuidNull())   {   DBDisplayString.SaveDisplay(languageCode,province.NameGuid,null,vDisplayTable);   }   else if (!province.IsNameNull())   {   if (province.IsNameGuidNull())   {   province.NameGuid = Guid.NewGuid();   }   DBDisplayString.SaveDisplay(languageCode,province.NameGuid,province.Name,vDisplayTable);   }   }   }   DataTableExtend[] dts = new DataTableExtend[4];   dts[0] = new DataTableExtend(ds.Port,"Port");   dts[1] = new DataTableExtend(ds.City, "City");   dts[2] = new DataTableExtend(ds.Province,"Province");   dts[3] = new DataTableExtend(ds.AddressDisStr,vDisplayTable);   SQLModify.ModifyDataBase(dts);
  }
  可以看出,這個操作會很麻煩,對於刪除操作而言,我們需要把該條記錄所有的多語言資料都刪掉,然後很不幸,對於資料集中已刪除了的記錄而言,雖然它還存在但卻不能訪問,更不幸的是,因為多資料表關聯的原因,我們甚至都不知道有多少資料被級連刪除了:(沒辦法,RejectChanges()吧,然後透過關聯找到所有被級連刪除的資料,把多語言資料都刪除掉,然後再刪除自身,注意到我這裡用到了Select方法,這是一個很方便的做法,減少了到資料庫的往返操作,從而以犧牲一些的代價節省了與資料庫痛心的時間。對於新增和修改操作,我們則負擔著另一項任務,即把Name欄位裡的資料根據使用者的當前語言,更新會資料庫相應的記錄中,這裡也會有很多種情況,如該欄位資料是新增的,預設語言的資料也沒有,當前語言的資料也沒有,或者是預設語言的資料有了當前語言的資料卻沒有,再或者使用者是把這個欄位的資料清空了,我們必須要找到多語言表中相應的記錄並刪除掉……等等,無奈,我們只好讓DBDisplayString.SaveDisplay()包辦掉這一切。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10794571/viewspace-974651/,如需轉載,請註明出處,否則將追究法律責任。

.net多語言和資料集內多資料表的處理(3) (轉)
請登入後發表評論 登入
全部評論

相關文章