View Full Version : سوال: مشکل فارسی با Aurelius و FireDac و Firebird
  
hp1361
پنج شنبه 15 خرداد 1393, 21:55 عصر
با سلام
من تصمیم گرفتم از Aurelius در برنامه ام استفاده کنم. اما مشکلی که دارم اینه که علی رغم اینکه فیلد ها از نوع string تعریف میشوند(که در دلفی XE5 از نوع Unicode است)  و در جدول Firebird همگه از نوع Varchar با Charset از نوع UTF8 تعریف میشوند اما زمانیکه اطلاعات فارسی ارسال میکنم همگی بصورت ؟؟؟؟؟  ذخیره میشوند!
این درحالیه که در زمانیکه از Aurelius استفاده نمیکردم مقدار پاس داده شده رو بصورت AsWideString ارسال میکنم و مشکلی پیش نمیامد
دوستان راه حلی دارند؟مشکل از کجاست؟ مربوط به FireDac میشه یا Firebird یا Aurelius؟
ممنون
hp1361
جمعه 16 خرداد 1393, 07:00 صبح
سلام
بانک اطلاعاتی رو تغییر دادم و از SQLite استفاده کردم مشکل مذکور ووجود نداشت و کلمات فارسی بدون مشکل در دیتابیس ذخیره شد.
البته باید اینو بگم که وقتی از SQLite استفاده میکنیم Aurelius مستقیما به فایل دیتابیس وصل میشه و از لایه کانکشن استفاده نمیکنه(مثلا از همون FDConnection با درایور SQLite)
آیا میشه نتیجه گرفت مشکل از FireDac هستش؟ چطور میشه مشکل رو حل کرد؟
hp1361
یک شنبه 18 خرداد 1393, 11:41 صبح
سلام
بعد از کلی کلنجار با FireDac به نتیجه ای نرسیدم.
لذا رفتم از FIBPlus استفاده کردم. خوشبختانه اطلاعات رو به درستی در دیتابیس ذخیره میکه و نمایش میده
البته در قیمت Plain text editor مربوط به IBExpert "مدیر ارشد" رو بصورت 
مدیر ارشد
و در Unicode editor هم به درستی 
مدیر ارشد
نمایش میده
لذا میشه نتیجه گرفت هر مشکلی هست در FireDac هست.
دوستان راه حلی ندارن. برادر عزیز عشایری، مشکل  دست شما رو میبوسه
ممنون.
BORHAN TEC
دوشنبه 19 خرداد 1393, 17:32 عصر
سلام
با این توضیحاتی که دادید بعیده که FireDac یا Firebird یا Aurelius باگی در این خصوص داشته باشند. فکر می کنم یکی از تنظیمات را در FireDAC انجام نداده اید و اون هم تنظیم خاصیت CharacterSet=utf8 مربوط به کامپوننت FDConnection هست.
موفق باشید...
hp1361
سه شنبه 20 خرداد 1393, 01:00 صبح
سلام
تمام این موارد رو  چک کردم اما نشد. UTF8,None,UNICODE_FSS و الی اخر
نسخه جدید Aurelius رو هم با XE6 تست کردم اما افاقه نکرد!
حتی MapRules رو هم تعریف کردم اما فرقی نکرد!
موندم پس چرا FIBPlus درست کار میکنه!
hp1361
سه شنبه 20 خرداد 1393, 10:52 صبح
سلام مجدد
دیروز از در انجمن FireDac سوال رو مطرح کردم و جواب دادن که اگر بدون استفاده از Aurelius اطلاعات به درستی ذخیره میشه، مشکل از تیم Aurelius هستش و سوال رو باید از اونا بپرسی!
منم مثل یه بچه خوب سوال رو از تیم پشتیبانی Aurelius  پرسیدم و در پاسخ گفتند:
By default, string properties in Aurelius are mapping as regular (Ansi) Varchar types in database. You have two options to solve this (and force Aurelius to use NVarchar):
1. Declare properties as WideString instead of string
2. Change Aurelius global configuration (note that this will affect *all* properties declared as string):
TGlobalConfigs.GetInstance.MapStringToNationalChar := true;
یعنی یا باید پروپرتی رو از نوع WideString تعریف کنیم و یا اینکه در تنظیمات Global مربوط به Aurelius مشخص کنیم که تمام اطلاعات بجای VarChar بصورت NVARCHAR ذخیره بشوند.
اگر بخواهیم از این دو روش استفاده کنیم اونوقت نه در FireDac و نه در Firebird نباید نوع Character Set رو UTF8 انتخاب کنیم در غیر این صورت ارور 
Cannot Transliterate character between Character Sets
با رعایت موارد فوق اطلاعات به درستی در جدول ذخیره و نمایش داده میشه . فقط موضوعی که قابل توجه است اینه که Charset  و Collate در جدول بصورت ISO8859_1 تعیین شده!
آیا این مورد مشکلی بوجود خواهد آورد؟
ویرایش 1 :
علی رغم اینکه اطلاعات در IBExpert درست نمایش داده میشه. اما زمانیکه اطلاعات رو در DBGrid نمایش میدم کماکان کاراکترهای ناخوانا نمایش داده میشه!
ویرایش 2 :
یکی از تنظیمات ای که TMS اعلام کرده بود رو انجام دادم . نوع Character Set  در FireDac رو NONE انتحاب نمودم. و نیز در قسمتMapRules از بخش  FormatOption مربوط به FireDac تنظیمات زیر رو انجام دادم
SourceDataType=>dtAnsiString
TargetDataType=>dtWideString
 و حالا اطلاعات به درستی در گرید دلفی نمایش داده میشود!
برای نمایش صحیح در IBExpert نیز باید در زمان ثبت دیتابیس مقدار Font Characters Set رو ARABIC_CHARSET انتخاب نمود.
فعلا این بهترین حالتی بود که بدست آوردم. اما هنوز نوع Collation , Character set در جدول  UTF8 نیست و ISO8859_1 میباشد!
مشکل روش ویرایش دوم :
هرچند اطلاعات در گرید و IBExpert درست نمایش داده می شوند  اما وقتی یک ShowMessage ساده میگیرم اطلاعات واکشی شده از دیتابیس عجق وجق! نمایش داده میشه که احتمالا همون AnsiString ست! و کلی دنگ و فنگ بعدی!
hp1361
دوشنبه 26 خرداد 1393, 08:54 صبح
سلام
تلاشمون برای استفاده از FireDac بهمراه Aurelius به جایی نرسید!
لذا سوییچ کردم به FIBPlus (بجای FireDac) و همه چیز به خوبی کار میکنه!
موفق باشیم
hp1361
سه شنبه 10 تیر 1393, 06:58 صبح
سلام مجدد به دوستان و آرزوی قبولی طاعات و عبادات
امروز بعد از سحر نشستم پای سیستم و با خودم گفتم نگاهی به کدهای Aurelius بندازم ببینم آیا چیزی ازش سردر میارم یا نه. که ناگهان متوجه یه چیزو در فایل Aurelius.Drivers.FireDac شدم!
تابعی یافتم بنام SetParams که حدس زدم وظیفه تعریف نوع ها در زمان استفاده از Aurelius  رو به عهده داره. لذا نگاهی به همین تابع در Aurelius.Drivers.FIBPlus انداختم که بدرستی تا بحال کار میکرد و دیدم بله! نوع فیلد ها که بصورت پارامتر ارجاع داده می شود در این تابع تعریف میشوند!
procedure TFireDacStatementAdapter.SetParams(Params: TEnumerable<TDBParam>);
var
  P: TDBParam;
  Parameter: TFDParam;
begin
  for P in Params do
  begin
    Parameter := FADQuery.ParamByName(P.ParamName);
    Parameter.DataType := P.ParamType;
    Parameter.Value := P.ParamValue;
  end;
end;
procedure TFIBPlusStatementAdapter.SetParams(Params: TEnumerable<TDBParam>);
var
  P: TDBParam;
  Parameter: TFIBXSQLVAR;
  Bytes: TBytesStream;
begin
  for P in Params do
  begin
    Parameter := FFIBQuery.ParamByName(P.ParamName);
    if VarIsNull(P.ParamValue) then
      Parameter.Clear
    else
    begin
      case P.ParamType of
        ftString:
          Parameter.AsString := P.ParamValue;
        ftSmallint, ftInteger, ftWord:
          Parameter.AsInteger := P.ParamValue;
        ftBoolean:
          Parameter.AsBoolean := P.ParamValue;
        ftFloat:
          Parameter.AsFloat := P.ParamValue;
        ftCurrency:
          Parameter.AsCurrency := P.ParamValue;
        ftDate:
          Parameter.AsDate := P.ParamValue;
        ftTime, ftDateTime:
          Parameter.AsDateTime := P.ParamValue;
        ftBlob:
          begin
            Bytes := TBytesStream.Create(TUtils.VariantToBytes(P.ParamV alue));
            try
              if VarIsNull(P.ParamValue) or (Bytes.Size = 0) then
                Parameter.Clear
              else
                Parameter.LoadFromStream(Bytes);
            finally
              Bytes.Free;
            end;
          end;
        ftWideMemo:
          Parameter.AsWideString := P.ParamValue;
        ftMemo:
          Parameter.AsString := P.ParamValue;
  //      ftGraphic: ;
  //      ftFmtMemo: ;
  //      ftParadoxOle: ;
  //      ftDBaseOle: ;
  //      ftTypedBinary: ;
  //      ftCursor: ;
        ftFixedChar:
          Parameter.AsString := P.ParamValue;
        ftWideString:
          Parameter.AsWideString := P.ParamValue;
        ftLargeint:
          Parameter.AsInt64 := P.ParamValue;
  //      ftADT: ;
  //      ftArray: ;
  //      ftReference: ;
  //      ftDataSet: ;
  //      ftOraBlob: ;
  //      ftOraClob: ;
  //      ftVariant: ;
  //      ftInterface: ;
  //      ftIDispatch: ;
  //      ftGuid: ;
        ftTimeStamp:
          Parameter.AsDateTime := P.ParamValue;
  //      ftFMTBcd: ;
        ftFixedWideChar:
          Parameter.AsWideString := P.ParamValue;
  //      ftOraTimeStamp: ;
  //      ftOraInterval: ;
        ftLongWord:
          Parameter.AsInt64 := P.ParamValue;
        ftShortint, ftByte:
          Parameter.AsInteger := P.ParamValue;
        ftExtended:
          Parameter.AsExtended := P.ParamValue;
  //      ftConnection: ;
  //      ftParams: ;
  //      ftStream: ;
  //      ftTimeStampOffset: ;
  //      ftObject: ;
        ftSingle:
          Parameter.AsFloat := P.ParamValue;
      else
        Assert(false, 'Data type parameter not supported in FIBPlus driver');
      end;
    end;
  end;
end;
لذا کدها رو از Aurelius.Drivers.FIBPlus به Aurelius.Drivers.FireDac کپی کردم و دیدم حالا Aurelius فیلدها رو به درستی در بانک ذخیره میکنه، به درستی در IBExpert نمایش داده میشه و نیز در برنامه به درستی رکورد ها نمایش داده میشوند!
برای اینکه خیلی در Aurelius.Drivers.FireDac دستکاری نکرده باشم صرفا اونو به شکل زیر تغییر دادم
procedure TFireDacStatementAdapter.SetParams(Params: TEnumerable<TDBParam>);
var
  P: TDBParam;
  Parameter: TFDParam;
begin
  for P in Params do
  begin
    Parameter := FADQuery.ParamByName(P.ParamName);
	if((P.ParamType=ftString) or (P.ParamType=ftMemo) or (P.ParamType=ftFixedChar)) then
		Parameter.AsWideString := P.ParamValue
	else
	begin
    Parameter.DataType := P.ParamType;
    Parameter.Value := P.ParamValue;
	end;
  end;
end;
دوستان در این خصوص نظری اگه دارند خوشحال خواهم شد
 
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.