PDA

View Full Version : کمبود Ram کامپیوتر در واکشی فایل بزرگ از دیتابیس



mokamel
دوشنبه 21 اردیبهشت 1394, 14:48 عصر
سلام
دوستان من تکه کدی دارم در برنامم شبیه زیر که کارش اینه که از دیتابیس یکسری اطلاعات که باینری شده است رو می خونه و میاره تو هارد ذخیره می کنه . نکته ای که هست اینه که اگه حجم فایل ها کم باشه مشکلی نیست اما وقتی یه فایل 500 مگابایتی که در دیتابیس ذخیره شده است و میخونه یهو ارورو مموری میده برنامه چرا ؟ و راه حل چیست ؟

using (sqlcomand)
{
sqlconection.Open();
sqlcomand.Connection = sqlconection;
sqlcomand.CommandText = "select FileContent from MyDB where [id]=@i ";
sqlcomand.Parameters.Add("@i", System.Data.SqlDbType.Int).Value = i;
tempbyte = (byte[])sqlcomand.ExecuteScalar();
sqlcomand.Parameters.RemoveAt("@i");
}
File.WriteAllBytes(pathfile, tempbyte);

fakhradin
دوشنبه 21 اردیبهشت 1394, 19:45 عصر
با سلام
هر بار که یه فایل رو فراخونی می کنید اون فایل توی رم باقی می مونه و کم کم میزان رم اختصاص به برنامه شما که فکر کنم توی ویژال استودیو به صورت پیش فرض باید 2 گیگ باشه پر می شه بهتره هر بار که فایلی رو می خونید کارتون باهاش تموم شد از رم پاک کنید از تابع های گاربج استفاده کنید
راه دیگه اینکه فایل ها رو چند بخشی و فشرده کنید و توی دیتابیس ذخیره کنید و یه لینک ارتباطی بین این فایل ها توی دیتابیس بزارید

mokamel
دوشنبه 21 اردیبهشت 1394, 19:48 عصر
یکی از دوستان پیشنهاد داده که تیکه تیکه اطلاعات رو بخون و قبلی رو حذف کن تا کمبود رم رخ نده یعتی چیزی شبیه جیت کامپایلر .
حالا چی هست و چطوری شما بگین ؟

nunegandom
سه شنبه 22 اردیبهشت 1394, 03:31 صبح
سلام
توی گوگل بزن split zip Csharp سورس هست

mokamel
سه شنبه 22 اردیبهشت 1394, 14:47 عصر
دوست بزرگوار این کد ها که شما فرمودید برای ذخیره اطلاعات توی دیتابیس هستش که فشرده کنیم و ...
در حالیکه من بر عکس همین کار و می خوام انجام بدم یعنی یسری اطلاعات باینری غیره فشرده توی دیتابیس هست که می خوام اون ها رو فراخوانی کنم و بیارم ت وبرنامه وسپس ذخیره کنم داخل هارد .

nunegandom
چهارشنبه 23 اردیبهشت 1394, 01:31 صبح
اکسپشن رو بگو...
اینه؟ MemoryOverload exception
اگه اینه از FileStream استفاده کن

mokamel
پنج شنبه 24 اردیبهشت 1394, 22:51 عصر
مهندس جان این ارور میده

An unhandled exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll

موقع خوندن فایل و همچنین وقتی دستور زیر رو میزنم
sqlcommnd.excutescaler();

mokamel
دوشنبه 28 اردیبهشت 1394, 14:52 عصر
نمی گم یه باسواد بلکه می گم یه خیر و دلسوز یعنی نیست یه کمکی کنه ؟
در ضمن حتی یکبار هم که دستور فوق اجرا میشه باز ارور مموری رو میده ( منظور اینکه ربطی به for نداره )

nunegandom
سه شنبه 29 اردیبهشت 1394, 04:06 صبح
از اونجایی که دات نت کالکشن محدود میکنه به حداکثر دو گیگ شما برنامت دچار مشکل میشه



using (sqlcomand)
{
sqlconection.Open();
sqlcomand.Connection = sqlconection;
sqlcomand.CommandText = "select FileContent from MyDB where [id]=@i ";
sqlcomand.Parameters.Add("@i", System.Data.SqlDbType.Int).Value = i;
tempbyte = (byte[])sqlcomand.ExecuteScalar();
sqlcomand.Parameters.RemoveAt("@i");
}


var first = tempbyte.Skip(0).Take(1000);
ByteArrayToFile(pathfile, first);
var second = tempbyte.Skip(1000).Take(1000);
ByteArrayToFile(pathfile, second);
}
public bool ByteArrayToFile(string _FileName, byte[] _ByteArray)
{
try
{
// Open file for reading
System.IO.FileStream _FileStream =
new System.IO.FileStream(_FileName, System.IO.FileMode.Create,
System.IO.FileAccess.Write);
// Writes a block of bytes to this stream using data from
// a byte array.
_FileStream.Write(_ByteArray, 0, _ByteArray.Length);


// close file stream
_FileStream.Close();


return true;
}
catch (Exception _Exception)
{
// Error
Console.WriteLine("Exception caught in process: {0}",
_Exception.ToString());
}


// error occured, return false
return false;
}

mokamel
سه شنبه 29 اردیبهشت 1394, 18:12 عصر
مهندس جان برنامه من تو خط 7 ( همین کدی که نوشتی و البته منم نوشتم ) ارور میده اصلا نمیرسه به اینکه بیاره تو مموری و من بخوام باهاش کاری کنم . یه تست کن اینم کوری ساخت دیتابیس

USE [master]
GO

CREATE DATABASE MyDB;
go

CREATE TABLE MyDB.dbo.MyTable
(
ID int IDENTITY(1,1) PRIMARY KEY ,
ContentFile varbinary(MAX) NOT NULL,
);

go

nunegandom
چهارشنبه 30 اردیبهشت 1394, 02:48 صبح
سلام، حواسم نبود شما باید اینجوری بنویسی

var first = ((byte[])sqlcomand.ExecuteScalar()).Skip(0).Take(1000); ByteArrayToFile(pathfile, first);
var second = ((byte[])sqlcomand.ExecuteScalar()).Skip(0).Take(1000);
ByteArrayToFile(pathfile, first);
بهتره بجای first و second یه حلقه بذاری و اینا رو توی لیست بذاری و در هر بار اجرای حلقه لیست رو new کنی
چیز دیگه اینکه من با Entity کار کردم و اونجا صد در صد جواب میده اگه خواستی Entity کد بزنی و این جواب نداد بگو کد بذارم

nunegandom
چهارشنبه 30 اردیبهشت 1394, 16:57 عصر
سلام دوستان
راستی من دیپلم ریاضی هستم مهندس نیستم :خجالت:
اینجا رو ببینید (http://stackoverflow.com/questions/14606006/exception-of-type-system-outofmemoryexception-was-thrown)

mokamel
چهارشنبه 30 اردیبهشت 1394, 22:32 عصر
مهندسی به سواد نه مدرک
حالا مندس جان میشه طلاعکدتون رو کامل و با یه جلقه For برای خوندن یه فایل باینری یا اندازه دو گیگ همینجا بزارین ؟

nunegandom
پنج شنبه 31 اردیبهشت 1394, 00:46 صبح
MyDB اسم جدوله؟ شما اصلا داری MyDB رو صدا میزنی ها... یعنی کل دیتابیس:قهقهه:

mokamel
پنج شنبه 31 اردیبهشت 1394, 10:03 صبح
بله حق با شکاست اینجا من اشتباه نوشتم . توی خود ویژوال درست نوشتم یعنی دقیقا
Select ContentFile From MyTable Where ID=@i

و دقیقا زمانی که
tempbyte = (byte[])sqlcomand.ExecuteScalar

صدا زده می شود . ارورو مموری اکسپشن را می دهد .

اگر واقعا مقدور است شما یک تیکه کد کامل که یک فایل دو گیگ را بتواند از دیتابیس ( 2008 ) که باینری ذخیره شده است را بخواند و در هارد ذخیره کند . بنویسید و نشر دهید . بسیار ممنون میشویم

nunegandom
جمعه 01 خرداد 1394, 21:43 عصر
باید بدون اینکه ببری توی حافظه مموری ثبتش کنی به این صورت

public void ByteCollector() {
List<string> MyByte = new List<string>();
foreach (var result in (byte[])sqlcomand.ExecuteScalar())
{


if (MyByte.Count % 500 == 0)
{
ByteArrayToFile(pathfile,MyByte);
MyByte = new List<string>();
}
MyByte.Add(result);
}
}
public bool ByteArrayToFile(string _FileName, byte[] _ByteArray)
{
try
{
// Open file for reading
System.IO.FileStream _FileStream =
new System.IO.FileStream(_FileName, System.IO.FileMode.Create,
System.IO.FileAccess.Write);
// Writes a block of bytes to this stream using data from
// a byte array.
_FileStream.Write(_ByteArray, 0, _ByteArray.Length);




// close file stream
_FileStream.Close();




return true;
}
catch (Exception _Exception)
{
// Error
Console.WriteLine("Exception caught in process: {0}",
_Exception.ToString());
}




// error occured, return false
return false;
}

nunegandom
جمعه 01 خرداد 1394, 21:44 عصر
اون ۵۰۰ کیلوبایت رو هم هرچقدر میخوای بذار

mokamel
شنبه 02 خرداد 1394, 11:25 صبح
عزیز این چجوریاست ؟
List<string> MyByte = new List<string>();

بعد متد اینه ؟


public bool ByteArrayToFile(string _FileName, byte[] _ByteArray)




منظور استرینگ ساختی بعد بایت ورودی دادی ؟

و نکته بعدی شما چه داخل حلقه از دستور زیر استفاده کردی :

(byte[])sqlcomand.ExecuteScalar()

درسته ؟ خوب من که از اولش گفتم که توی این دوستر ارور مموری دارم . شما به هر حال با اجرای این دوستور به برنامه گفتی برو اطلاعات باینری رو وردار بیار . یعنی باز رفته تو حافظه . پس اگر بره تو حافظه دیگه نیاز به جلقه نیست چون ارور نداده و به راحتی می شه نوشتش .

مهم اینه که برنامه توا ین خط ارور مموری نگیره .
البته من هنوز موفق به تست برنامه شما نشدم چون ایراد اروگومان میگیره همینی که بالا گفتم . اما پیشنهاد می دم که باید یکاری کنید که مثلا در پکت های 1000 بایتی بره و اطلاعا تو از دیتابیس بگیره .