พื้นที่เก็บข้อมูล EntityFramework แถวทั้งหมดส่งคืนค่าว่าง

สรุป

ฉันได้แก้ไขโซลูชัน nopCommerce เพื่อรวมเอนทิตีใหม่ด้วยแนวทาง CodeFirst ซึ่งได้อัปเดตฐานข้อมูลได้สำเร็จดังที่แสดงในภาพด้านล่าง

รูปภาพที่ฐานข้อมูลมีการอัปเดตตาราง

เมื่อฉันพยายามเข้าถึงตารางพื้นที่เก็บข้อมูลซึ่งถูกแทรกผ่าน AutoFrac ฉันจะได้รับแถวที่ส่งคืนโดยพื้นที่เก็บข้อมูล แต่คอลัมน์ทั้งหมดแสดงค่าว่าง โปรดทราบว่าจำนวนแถวในตารางจะเหมือนกับจำนวนที่เห็นในตารางฐานข้อมูล ดังนั้นจึงดูเหมือนว่าจะเชื่อมต่อกันแต่ไม่แสดงค่า

พื้นที่เก็บข้อมูลการเรียกโค้ด

{
    public partial class NutrientService : INutrientService
    {
        #region fields

        protected readonly IRepository<ProductNutrient> _productNutrientRepository;

        #endregion fields

        #region Ctor

        public NutrientService(IRepository<ProductNutrient> productNutrientRepository)
        {
            _productNutrientRepository = productNutrientRepository;
        }

        #endregion Ctor

        public IList<ProductNutrient> GetNutrients()
        {
            var query = from p in _productNutrientRepository.Table
                        select p as ProductNutrient;
            var list = query.ToList();
            return list;
        }

        public IList<ProductNutrient> GetNutrientsByProductID()
        {
           
            var query = from p in _productNutrientRepository.Table
                        select p as ProductNutrient;
            var list = query.ToList();
            return list;
        }
    }
} 

การดีบักแสดงค่า Null ที่ส่งคืนจากพื้นที่เก็บข้อมูล

คำจำกัดความของตารางใน SQL Management Studio

คำจำกัดความเอนทิตีในโค้ด

    public class ProductNutrient : BaseEntity
    {
        public int NutrientID;

        public int ProductID;

        public string Nutrient;

        public bool ShowLessThan;

        public decimal Value;

        public string Unit;
    }
}

พื้นที่เก็บข้อมูลใช้งานได้กับตารางอื่น แต่นี่คือรหัสของพื้นที่เก็บข้อมูลอยู่ดี

      /// </summary>
        public virtual IQueryable<TEntity> Table => Entities;

        /// <summary>
        /// Gets an entity set
        /// </summary>
        protected virtual ITable<TEntity> Entities => _entities ?? (_entities = _dataProvider.GetTable<TEntity>());


        #endregion
    }

person DanCRichards    schedule 06.01.2021    source แหล่งที่มา
comment
กรุณาอย่าโพสต์โค้ดและผลลัพธ์เป็นรูปภาพ ไม่สามารถคัดลอก (บางส่วน) เพื่อตอบได้ และข้อความจะไม่ปรากฏในเครื่องมือค้นหา รูปภาพควรใช้เป็นทางเลือกสุดท้ายเท่านั้น   -  person Gert Arnold    schedule 07.01.2021
comment
อัพเดทแล้ว ขอบคุณครับ. นี่เป็นโพสต์แรกของฉันถึง SO เราหวังว่าคุณจะสามารถให้การสนับสนุนเกี่ยวกับปัญหานี้ได้เช่นกัน ขอบคุณแดน   -  person DanCRichards    schedule 07.01.2021
comment
select p as ProductNutrient; อาจจะไม่ทำตามที่คุณคิด p เป็นอย่างอื่น ทำไมคุณถึงโยนมันต่อไป? แต่เราไม่สามารถมองเห็นพื้นที่เก็บข้อมูลได้ (โดยเฉพาะสิ่งที่อยู่เบื้องหลัง _productNutrientRepository.Table) และถึงกระนั้น ก็สามารถถามคำถามได้โดยไม่ต้องใช้รูปภาพทั้งหมด   -  person Gert Arnold    schedule 07.01.2021
comment
ฉันสงสัยว่า _productNutrientRepository.Table นี้คืออะไร คุณช่วยแสดงรหัส _productNutrientRepository และรหัสตารางให้เราหน่อยได้ไหม   -  person Serge    schedule 07.01.2021
comment
เฮ้ @Sergey ฉันได้อัปเดตโพสต์เพื่อแสดงสิ่งนี้ มีบริการอื่นๆ ในโปรเจ็กต์ของฉันที่อ้างอิงถึงอินเทอร์เฟซของพื้นที่เก็บข้อมูลและทำงานได้ดี ฉันสับสนเล็กน้อยว่าทำไม _productNutrientRepository.Table จึงแสดงรายการในรายการ แต่มีค่าว่าง ยังเกิดขึ้นเมื่อฉันใส่ค่า มันแค่สร้างเรคคอร์ดที่เป็นโมฆะ   -  person DanCRichards    schedule 07.01.2021
comment
@GertArnold คุณอาจไม่จำเป็นต้องกังวลเกี่ยวกับการช่วยเหลือฉันในเรื่องนี้ ขอบคุณ!   -  person DanCRichards    schedule 07.01.2021


คำตอบ (1)


ฉันสงสัยว่าคุณกำลังหลงทางอยู่ในนามธรรม หรืออย่างน้อยพวกเขาก็ปกปิดปัญหาไว้

เริ่มต้นด้วยการแยกนามธรรมทั้งหมดของคุณออกโดยทำหน้าที่เป็นพื้นที่เก็บข้อมูล ฉีด DbContext แทนเป็นจุดเริ่มต้น:

protected readonly AppDbContext _context = null;

public NutrientService(AppDbContext context)
{
    _context = context ?? throw new ArgumentNullException("context");
}

public IList<ProductNutrient> GetNutrients()
{
    var productNutrients = context.ProductNutrients
        .ToList();

    return productNutrients;
}

สิ่งนี้ส่งคืนข้อมูลทั้งหมดหรือค่าว่างหรือไม่ หากยังว่างเปล่า คุณจะต้องตรวจสอบสตริงการเชื่อมต่อที่ใช้งานในขณะรันไทม์ เนื่องจากอาจชี้ไปที่อินสแตนซ์ฐานข้อมูลเก่ากว่าที่คุณกำลังดูอยู่ นี่ดูเหมือนจะเป็นปัญหาทั่วไปที่ผู้คนใช้ SSMS หรือนักออกแบบเพื่อตรวจสอบสคีมา DB แต่แล้วรันไทม์ web/app.config ชี้ไปที่ตำแหน่ง DB ที่เก่ากว่าหรือแชร์ หรือฐานข้อมูลที่ถูกสร้างขึ้นซึ่งมีข้อมูลบางส่วน แต่ไม่ใช่สิ่งที่คุณคาดหวังที่จะเห็น

หากส่งคืนข้อมูลที่คุณคาดหวัง แสดงว่าสิ่งที่เป็นนามธรรม (พื้นที่เก็บข้อมูล) ของคุณมีข้อบกพร่องในทางใดทางหนึ่ง คำถามแรกก็คือ เหตุใดคุณจึงใช้ Repository รอบ ๆ DbContext คำแนะนำของฉันเมื่อพูดถึงพื้นที่เก็บข้อมูลก็คือ Generic Repositories เช่น Repository<ProductNutrient> เป็นการต่อต้านรูปแบบที่แย่มาก หากคุณกำลังใช้งาน Repository เนื่องจากคุณพบตัวอย่างหนึ่ง คุณจะต้องเข้าใจเหตุผลที่ซ่อนอยู่ หากคุณกำลังใช้ Repository เพื่อซ่อนความจริงที่ว่าคุณกำลังใช้ EntityFramework หรือซ่อน DbContext แสดงว่า IMHO นี่เป็นเหตุผลที่ผิดในการใช้ Repository เหตุผลเดียวที่ต้องพิจารณาใช้รูปแบบ Repository บน EntityFramework คือทำให้โค้ดของคุณง่ายต่อการทดสอบหน่วย ในการทำเช่นนั้น ฉันขอแนะนำอย่างยิ่งให้ใช้ประโยชน์จาก IQueryable<TEntity> เป็นประเภทการคืนสินค้า อาจเป็นไปได้ว่า .Table กำลังส่งคืน IQueryable<ProductNutrient> แต่ถ้ามันส่งคืน DbSet<ProductNutrient> คุณก็อาจจะใช้ DbContext เช่นกัน หากส่งคืนค่าประมาณ IEnumerable<ProductNutrient> แสดงว่าคุณอาจปล่อยให้ระบบของคุณเปิดรับข้อจำกัดด้านประสิทธิภาพที่สำคัญในอนาคต เนื่องจากคุณสูญเสียความสามารถส่วนใหญ่ที่ EF สามารถให้ได้

หากคุณไม่ได้วางแผนที่จะใช้การทดสอบหน่วยโดยที่คุณจะต้องจำลองชั้นข้อมูลของคุณเพื่อให้การทดสอบมีสถานะที่ทราบที่เชื่อถือได้ ก็ไม่มีเหตุผลใด ๆ ที่จะสร้างคลาส Repository และอาจกำหนดข้อจำกัดที่มีค่าใช้จ่ายสูงมากในการเข้าถึงข้อมูลของคุณ ฉันสรุปปัญหาเกี่ยวกับรูปแบบ Generic Repository และ EF ในคำตอบของฉันสำหรับคำถามนี้: (วิธีการตั้งค่าหลายบริการจาก Entity Framework Core บน Repository Pattern) คุณสามารถทดสอบโค้ดทั้งหมดที่ใช้ DbContext โดยใช้อิมเมจฐานข้อมูลทดสอบการรวมเฉพาะ หรือฐานข้อมูลในหน่วยความจำ หรือทำงานเพิ่มอีกเล็กน้อย โดยเยาะเย้ย DbContext/DbSets สำหรับการทดสอบหน่วยซึ่งดำเนินการซ้ำๆ ระหว่างการพัฒนาก่อนที่จะรวมเข้าด้วยกัน การเยาะเย้ยคลาส Repository นั้นง่ายกว่ามาก

person Steve Py    schedule 06.01.2021
comment
ขอบคุณสำหรับความช่วยเหลือ การดู DBContext ช่วยแก้ปัญหาได้ การเลิกใช้โมเดล Repo นั้นไม่คุ้มค่า ฉันกำลังทำงานกับเฟรมเวิร์ก OpenSource ที่ใช้งานมัน และการใช้เวลาเพื่อเปลี่ยนแปลงสิ่งเหล่านั้นทั้งหมดจะไม่ให้คุณค่าที่สำคัญในการรับประกันการเปลี่ยนแปลง - person DanCRichards; 08.01.2021